blob: d654148883491f83fee46fe627cc9d8f14bd8812 [file] [log] [blame]
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001/*
2 * Infinity Unlimited USB Phoenix driver
3 *
4 * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
5 *
6 * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * And tested with help of WB Electronics
14 *
15 */
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/init.h>
19#include <linux/slab.h>
20#include <linux/tty.h>
21#include <linux/tty_driver.h>
22#include <linux/tty_flip.h>
23#include <linux/serial.h>
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/spinlock.h>
27#include <linux/uaccess.h>
28#include <linux/usb.h>
29#include <linux/usb/serial.h>
30#include "iuu_phoenix.h"
31#include <linux/random.h>
32
33
34#ifdef CONFIG_USB_SERIAL_DEBUG
35static int debug = 1;
36#else
37static int debug;
38#endif
39
40/*
41 * Version Information
42 */
43#define DRIVER_VERSION "v0.5"
44#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
45
46static struct usb_device_id id_table[] = {
47 {USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)},
48 {} /* Terminating entry */
49};
50MODULE_DEVICE_TABLE(usb, id_table);
51
52static struct usb_driver iuu_driver = {
53 .name = "iuu_phoenix",
54 .probe = usb_serial_probe,
55 .disconnect = usb_serial_disconnect,
56 .id_table = id_table,
57 .no_dynamic_id = 1,
58};
59
60/* turbo parameter */
61static int boost = 100;
62static int clockmode = 1;
63static int cdmode = 1;
64static int iuu_cardin;
65static int iuu_cardout;
66static int xmas;
67
68static void read_rxcmd_callback(struct urb *urb);
69
70struct iuu_private {
71 spinlock_t lock; /* store irq state */
72 wait_queue_head_t delta_msr_wait;
73 u8 line_control;
74 u8 line_status;
75 u8 termios_initialized;
76 int tiostatus; /* store IUART SIGNAL for tiocmget call */
77 u8 reset; /* if 1 reset is needed */
78 int poll; /* number of poll */
79 u8 *writebuf; /* buffer for writing to device */
80 int writelen; /* num of byte to write to device */
81 u8 *buf; /* used for initialize speed */
82 u8 *dbgbuf; /* debug buffer */
83 u8 len;
84};
85
86
87static void iuu_free_buf(struct iuu_private *priv)
88{
89 kfree(priv->buf);
90 kfree(priv->dbgbuf);
91 kfree(priv->writebuf);
92}
93
94static int iuu_alloc_buf(struct iuu_private *priv)
95{
96 priv->buf = kzalloc(256, GFP_KERNEL);
97 priv->dbgbuf = kzalloc(256, GFP_KERNEL);
98 priv->writebuf = kzalloc(256, GFP_KERNEL);
99 if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
100 iuu_free_buf(priv);
Harvey Harrison441b62c2008-03-03 16:08:34 -0800101 dbg("%s problem allocation buffer", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200102 return -ENOMEM;
103 }
Harvey Harrison441b62c2008-03-03 16:08:34 -0800104 dbg("%s - Privates buffers allocation success", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200105 return 0;
106}
107
108static int iuu_startup(struct usb_serial *serial)
109{
110 struct iuu_private *priv;
111 priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
Harvey Harrison441b62c2008-03-03 16:08:34 -0800112 dbg("%s- priv allocation success", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200113 if (!priv)
114 return -ENOMEM;
115 if (iuu_alloc_buf(priv)) {
116 kfree(priv);
117 return -ENOMEM;
118 }
119 spin_lock_init(&priv->lock);
120 init_waitqueue_head(&priv->delta_msr_wait);
121 usb_set_serial_port_data(serial->port[0], priv);
122 return 0;
123}
124
125/* Shutdown function */
126static void iuu_shutdown(struct usb_serial *serial)
127{
128 struct usb_serial_port *port = serial->port[0];
129 struct iuu_private *priv = usb_get_serial_port_data(port);
130 if (!port)
131 return;
132
Harvey Harrison441b62c2008-03-03 16:08:34 -0800133 dbg("%s", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200134
135 if (priv) {
136 iuu_free_buf(priv);
Harvey Harrison441b62c2008-03-03 16:08:34 -0800137 dbg("%s - I will free all", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200138 usb_set_serial_port_data(port, NULL);
139
Harvey Harrison441b62c2008-03-03 16:08:34 -0800140 dbg("%s - priv is not anymore in port structure", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200141 kfree(priv);
142
Harvey Harrison441b62c2008-03-03 16:08:34 -0800143 dbg("%s priv is now kfree", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200144 }
145}
146
Alan Cox95da3102008-07-22 11:09:07 +0100147static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200148 unsigned int set, unsigned int clear)
149{
Alan Cox95da3102008-07-22 11:09:07 +0100150 struct usb_serial_port *port = tty->driver_data;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200151 struct iuu_private *priv = usb_get_serial_port_data(port);
Alan Cox7b1fc8b2008-02-20 21:39:25 +0000152 unsigned long flags;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200153
Alan Cox7b1fc8b2008-02-20 21:39:25 +0000154 /* FIXME: locking on tiomstatus */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800155 dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __func__,
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200156 port->number, set, clear);
Alan Cox7b1fc8b2008-02-20 21:39:25 +0000157
158 spin_lock_irqsave(&priv->lock, flags);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200159 if (set & TIOCM_RTS)
160 priv->tiostatus = TIOCM_RTS;
161
162 if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800163 dbg("%s TIOCMSET RESET called !!!", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200164 priv->reset = 1;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200165 }
Alan Cox7b1fc8b2008-02-20 21:39:25 +0000166 spin_unlock_irqrestore(&priv->lock, flags);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200167 return 0;
168}
169
170/* This is used to provide a carrier detect mechanism
171 * When a card is present, the response is 0x00
172 * When no card , the reader respond with TIOCM_CD
173 * This is known as CD autodetect mechanism
174 */
Alan Cox95da3102008-07-22 11:09:07 +0100175static int iuu_tiocmget(struct tty_struct *tty, struct file *file)
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200176{
Alan Cox95da3102008-07-22 11:09:07 +0100177 struct usb_serial_port *port = tty->driver_data;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200178 struct iuu_private *priv = usb_get_serial_port_data(port);
Alan Cox7b1fc8b2008-02-20 21:39:25 +0000179 unsigned long flags;
180 int rc;
181
182 spin_lock_irqsave(&priv->lock, flags);
183 rc = priv->tiostatus;
184 spin_unlock_irqrestore(&priv->lock, flags);
185
186 return rc;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200187}
188
189static void iuu_rxcmd(struct urb *urb)
190{
Ming Leicdc97792008-02-24 18:41:47 +0800191 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200192 int result;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800193 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200194
195 if (urb->status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800196 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200197 /* error stop all */
198 return;
199 }
200
201
202 memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
203 usb_fill_bulk_urb(port->write_urb, port->serial->dev,
204 usb_sndbulkpipe(port->serial->dev,
205 port->bulk_out_endpointAddress),
206 port->write_urb->transfer_buffer, 1,
207 read_rxcmd_callback, port);
208 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
209}
210
211static int iuu_reset(struct usb_serial_port *port, u8 wt)
212{
213 struct iuu_private *priv = usb_get_serial_port_data(port);
214 int result;
215 char *buf_ptr = port->write_urb->transfer_buffer;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800216 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200217
218 /* Prepare the reset sequence */
219
220 *buf_ptr++ = IUU_RST_SET;
221 *buf_ptr++ = IUU_DELAY_MS;
222 *buf_ptr++ = wt;
223 *buf_ptr = IUU_RST_CLEAR;
224
225 /* send the sequence */
226
227 usb_fill_bulk_urb(port->write_urb,
228 port->serial->dev,
229 usb_sndbulkpipe(port->serial->dev,
230 port->bulk_out_endpointAddress),
231 port->write_urb->transfer_buffer, 4, iuu_rxcmd, port);
232 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
233 priv->reset = 0;
234 return result;
235}
236
237/* Status Function
238 * Return value is
239 * 0x00 = no card
240 * 0x01 = smartcard
241 * 0x02 = sim card
242 */
243static void iuu_update_status_callback(struct urb *urb)
244{
Ming Leicdc97792008-02-24 18:41:47 +0800245 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200246 struct iuu_private *priv = usb_get_serial_port_data(port);
247 u8 *st;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800248 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200249
250 if (urb->status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800251 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200252 /* error stop all */
253 return;
254 }
255
256 st = urb->transfer_buffer;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800257 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200258 if (urb->actual_length == 1) {
259 switch (st[0]) {
260 case 0x1:
261 priv->tiostatus = iuu_cardout;
262 break;
263 case 0x0:
264 priv->tiostatus = iuu_cardin;
265 break;
266 default:
267 priv->tiostatus = iuu_cardin;
268 }
269 }
270 iuu_rxcmd(urb);
271}
272
273static void iuu_status_callback(struct urb *urb)
274{
Ming Leicdc97792008-02-24 18:41:47 +0800275 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200276 int result;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800277 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200278
Harvey Harrison441b62c2008-03-03 16:08:34 -0800279 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200280 usb_fill_bulk_urb(port->read_urb, port->serial->dev,
281 usb_rcvbulkpipe(port->serial->dev,
282 port->bulk_in_endpointAddress),
283 port->read_urb->transfer_buffer, 256,
284 iuu_update_status_callback, port);
285 result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
286}
287
288static int iuu_status(struct usb_serial_port *port)
289{
290 int result;
291
Harvey Harrison441b62c2008-03-03 16:08:34 -0800292 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200293
294 memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
295 usb_fill_bulk_urb(port->write_urb, port->serial->dev,
296 usb_sndbulkpipe(port->serial->dev,
297 port->bulk_out_endpointAddress),
298 port->write_urb->transfer_buffer, 1,
299 iuu_status_callback, port);
300 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
301 return result;
302
303}
304
305static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
306{
307 int status;
308 struct usb_serial *serial = port->serial;
309 int actual = 0;
310
Harvey Harrison441b62c2008-03-03 16:08:34 -0800311 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200312
313 /* send the data out the bulk port */
314
315 status =
316 usb_bulk_msg(serial->dev,
317 usb_sndbulkpipe(serial->dev,
318 port->bulk_out_endpointAddress), buf,
319 count, &actual, HZ * 1);
320
321 if (status != IUU_OPERATION_OK) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800322 dbg("%s - error = %2x", __func__, status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200323 } else {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800324 dbg("%s - write OK !", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200325 }
326 return status;
327}
328
329static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
330{
331 int status;
332 struct usb_serial *serial = port->serial;
333 int actual = 0;
334
Harvey Harrison441b62c2008-03-03 16:08:34 -0800335 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200336
337 /* send the data out the bulk port */
338
339 status =
340 usb_bulk_msg(serial->dev,
341 usb_rcvbulkpipe(serial->dev,
342 port->bulk_in_endpointAddress), buf,
343 count, &actual, HZ * 1);
344
345 if (status != IUU_OPERATION_OK) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800346 dbg("%s - error = %2x", __func__, status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200347 } else {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800348 dbg("%s - read OK !", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200349 }
350
351 return status;
352}
353
354static int iuu_led(struct usb_serial_port *port, unsigned int R,
355 unsigned int G, unsigned int B, u8 f)
356{
357 int status;
358 u8 *buf;
359 buf = kmalloc(8, GFP_KERNEL);
360 if (!buf)
361 return -ENOMEM;
362
Harvey Harrison441b62c2008-03-03 16:08:34 -0800363 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200364
365 buf[0] = IUU_SET_LED;
366 buf[1] = R & 0xFF;
367 buf[2] = (R >> 8) & 0xFF;
368 buf[3] = G & 0xFF;
369 buf[4] = (G >> 8) & 0xFF;
370 buf[5] = B & 0xFF;
371 buf[6] = (B >> 8) & 0xFF;
372 buf[7] = f;
373 status = bulk_immediate(port, buf, 8);
374 kfree(buf);
375 if (status != IUU_OPERATION_OK)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800376 dbg("%s - led error status = %2x", __func__, status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200377 else
Harvey Harrison441b62c2008-03-03 16:08:34 -0800378 dbg("%s - led OK !", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200379 return IUU_OPERATION_OK;
380}
381
382static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
383 u8 b2, u8 freq)
384{
385 *buf++ = IUU_SET_LED;
386 *buf++ = r1;
387 *buf++ = r2;
388 *buf++ = g1;
389 *buf++ = g2;
390 *buf++ = b1;
391 *buf++ = b2;
392 *buf = freq;
393}
394
395static void iuu_led_activity_on(struct urb *urb)
396{
Ming Leicdc97792008-02-24 18:41:47 +0800397 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200398 int result;
399 char *buf_ptr = port->write_urb->transfer_buffer;
400 *buf_ptr++ = IUU_SET_LED;
401 if (xmas == 1) {
402 get_random_bytes(buf_ptr, 6);
403 *(buf_ptr+7) = 1;
404 } else {
405 iuu_rgbf_fill_buffer(buf_ptr, 255, 255, 0, 0, 0, 0, 255);
406 }
407
408 usb_fill_bulk_urb(port->write_urb, port->serial->dev,
409 usb_sndbulkpipe(port->serial->dev,
410 port->bulk_out_endpointAddress),
411 port->write_urb->transfer_buffer, 8 ,
412 iuu_rxcmd, port);
413 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
414}
415
416static void iuu_led_activity_off(struct urb *urb)
417{
Ming Leicdc97792008-02-24 18:41:47 +0800418 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200419 int result;
420 char *buf_ptr = port->write_urb->transfer_buffer;
421 if (xmas == 1) {
422 iuu_rxcmd(urb);
423 return;
424 } else {
425 *buf_ptr++ = IUU_SET_LED;
426 iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255);
427 }
428 usb_fill_bulk_urb(port->write_urb, port->serial->dev,
429 usb_sndbulkpipe(port->serial->dev,
430 port->bulk_out_endpointAddress),
431 port->write_urb->transfer_buffer, 8 ,
432 iuu_rxcmd, port);
433 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
434}
435
436
437
438static int iuu_clk(struct usb_serial_port *port, int dwFrq)
439{
440 int status;
441 struct iuu_private *priv = usb_get_serial_port_data(port);
442 int Count = 0;
443 u8 FrqGenAdr = 0x69;
444 u8 DIV = 0; /* 8bit */
445 u8 XDRV = 0; /* 8bit */
446 u8 PUMP = 0; /* 3bit */
447 u8 PBmsb = 0; /* 2bit */
448 u8 PBlsb = 0; /* 8bit */
449 u8 PO = 0; /* 1bit */
450 u8 Q = 0; /* 7bit */
451 /* 24bit = 3bytes */
452 unsigned int P = 0;
453 unsigned int P2 = 0;
454 int frq = (int)dwFrq;
455
Harvey Harrison441b62c2008-03-03 16:08:34 -0800456 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200457
458 if (frq == 0) {
459 priv->buf[Count++] = IUU_UART_WRITE_I2C;
460 priv->buf[Count++] = FrqGenAdr << 1;
461 priv->buf[Count++] = 0x09;
462 priv->buf[Count++] = 0x00;
463
464 status = bulk_immediate(port, (u8 *) priv->buf, Count);
465 if (status != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800466 dbg("%s - write error ", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200467 return status;
468 }
469 } else if (frq == 3579000) {
470 DIV = 100;
471 P = 1193;
472 Q = 40;
473 XDRV = 0;
474 } else if (frq == 3680000) {
475 DIV = 105;
476 P = 161;
477 Q = 5;
478 XDRV = 0;
479 } else if (frq == 6000000) {
480 DIV = 66;
481 P = 66;
482 Q = 2;
483 XDRV = 0x28;
484 } else {
485 unsigned int result = 0;
486 unsigned int tmp = 0;
487 unsigned int check;
488 unsigned int check2;
489 char found = 0x00;
490 unsigned int lQ = 2;
491 unsigned int lP = 2055;
492 unsigned int lDiv = 4;
493
494 for (lQ = 2; lQ <= 47 && !found; lQ++)
495 for (lP = 2055; lP >= 8 && !found; lP--)
496 for (lDiv = 4; lDiv <= 127 && !found; lDiv++) {
497 tmp = (12000000 / lDiv) * (lP / lQ);
498 if (abs((int)(tmp - frq)) <
499 abs((int)(frq - result))) {
500 check2 = (12000000 / lQ);
501 if (check2 < 250000)
502 continue;
503 check = (12000000 / lQ) * lP;
504 if (check > 400000000)
505 continue;
506 if (check < 100000000)
507 continue;
508 if (lDiv < 4 || lDiv > 127)
509 continue;
510 result = tmp;
511 P = lP;
512 DIV = lDiv;
513 Q = lQ;
514 if (result == frq)
515 found = 0x01;
516 }
517 }
518 }
519 P2 = ((P - PO) / 2) - 4;
520 DIV = DIV;
521 PUMP = 0x04;
522 PBmsb = (P2 >> 8 & 0x03);
523 PBlsb = P2 & 0xFF;
524 PO = (P >> 10) & 0x01;
525 Q = Q - 2;
526
527 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
528 priv->buf[Count++] = FrqGenAdr << 1;
529 priv->buf[Count++] = 0x09;
530 priv->buf[Count++] = 0x20; /* Adr = 0x09 */
531 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
532 priv->buf[Count++] = FrqGenAdr << 1;
533 priv->buf[Count++] = 0x0C;
534 priv->buf[Count++] = DIV; /* Adr = 0x0C */
535 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
536 priv->buf[Count++] = FrqGenAdr << 1;
537 priv->buf[Count++] = 0x12;
538 priv->buf[Count++] = XDRV; /* Adr = 0x12 */
539 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
540 priv->buf[Count++] = FrqGenAdr << 1;
541 priv->buf[Count++] = 0x13;
542 priv->buf[Count++] = 0x6B; /* Adr = 0x13 */
543 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
544 priv->buf[Count++] = FrqGenAdr << 1;
545 priv->buf[Count++] = 0x40;
546 priv->buf[Count++] = (0xC0 | ((PUMP & 0x07) << 2)) |
547 (PBmsb & 0x03); /* Adr = 0x40 */
548 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
549 priv->buf[Count++] = FrqGenAdr << 1;
550 priv->buf[Count++] = 0x41;
551 priv->buf[Count++] = PBlsb; /* Adr = 0x41 */
552 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
553 priv->buf[Count++] = FrqGenAdr << 1;
554 priv->buf[Count++] = 0x42;
555 priv->buf[Count++] = Q | (((PO & 0x01) << 7)); /* Adr = 0x42 */
556 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
557 priv->buf[Count++] = FrqGenAdr << 1;
558 priv->buf[Count++] = 0x44;
559 priv->buf[Count++] = (char)0xFF; /* Adr = 0x44 */
560 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
561 priv->buf[Count++] = FrqGenAdr << 1;
562 priv->buf[Count++] = 0x45;
563 priv->buf[Count++] = (char)0xFE; /* Adr = 0x45 */
564 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
565 priv->buf[Count++] = FrqGenAdr << 1;
566 priv->buf[Count++] = 0x46;
567 priv->buf[Count++] = 0x7F; /* Adr = 0x46 */
568 priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
569 priv->buf[Count++] = FrqGenAdr << 1;
570 priv->buf[Count++] = 0x47;
571 priv->buf[Count++] = (char)0x84; /* Adr = 0x47 */
572
573 status = bulk_immediate(port, (u8 *) priv->buf, Count);
574 if (status != IUU_OPERATION_OK)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800575 dbg("%s - write error ", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200576 return status;
577}
578
579static int iuu_uart_flush(struct usb_serial_port *port)
580{
581 int i;
582 int status;
583 u8 rxcmd = IUU_UART_RX;
584 struct iuu_private *priv = usb_get_serial_port_data(port);
585
Harvey Harrison441b62c2008-03-03 16:08:34 -0800586 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200587
588 if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
589 return -EIO;
590
591 for (i = 0; i < 2; i++) {
592 status = bulk_immediate(port, &rxcmd, 1);
593 if (status != IUU_OPERATION_OK) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800594 dbg("%s - uart_flush_write error", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200595 return status;
596 }
597
598 status = read_immediate(port, &priv->len, 1);
599 if (status != IUU_OPERATION_OK) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800600 dbg("%s - uart_flush_read error", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200601 return status;
602 }
603
604 if (priv->len > 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800605 dbg("%s - uart_flush datalen is : %i ", __func__,
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200606 priv->len);
607 status = read_immediate(port, priv->buf, priv->len);
608 if (status != IUU_OPERATION_OK) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800609 dbg("%s - uart_flush_read error", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200610 return status;
611 }
612 }
613 }
Harvey Harrison441b62c2008-03-03 16:08:34 -0800614 dbg("%s - uart_flush_read OK!", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200615 iuu_led(port, 0, 0xF000, 0, 0xFF);
616 return status;
617}
618
619static void read_buf_callback(struct urb *urb)
620{
Ming Leicdc97792008-02-24 18:41:47 +0800621 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200622 unsigned char *data = urb->transfer_buffer;
623 struct tty_struct *tty;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800624 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200625
626 if (urb->status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800627 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200628 if (urb->status == -EPROTO) {
629 /* reschedule needed */
630 }
631 return;
632 }
633
Harvey Harrison441b62c2008-03-03 16:08:34 -0800634 dbg("%s - %i chars to write", __func__, urb->actual_length);
Alan Cox95da3102008-07-22 11:09:07 +0100635 tty = port->port.tty;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200636 if (data == NULL)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800637 dbg("%s - data is NULL !!!", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200638 if (tty && urb->actual_length && data) {
639 tty_insert_flip_string(tty, data, urb->actual_length);
640 tty_flip_buffer_push(tty);
641 }
642 iuu_led_activity_on(urb);
643}
644
645static int iuu_bulk_write(struct usb_serial_port *port)
646{
647 struct iuu_private *priv = usb_get_serial_port_data(port);
Steven Rostedt85943032008-05-06 20:42:31 -0700648 unsigned long flags;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200649 int result;
650 int i;
651 char *buf_ptr = port->write_urb->transfer_buffer;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800652 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200653
654 *buf_ptr++ = IUU_UART_ESC;
655 *buf_ptr++ = IUU_UART_TX;
656 *buf_ptr++ = priv->writelen;
657
658 memcpy(buf_ptr, priv->writebuf,
659 priv->writelen);
660 if (debug == 1) {
661 for (i = 0; i < priv->writelen; i++)
662 sprintf(priv->dbgbuf + i*2 ,
663 "%02X", priv->writebuf[i]);
664 priv->dbgbuf[priv->writelen+i*2] = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800665 dbg("%s - writing %i chars : %s", __func__,
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200666 priv->writelen, priv->dbgbuf);
667 }
668 usb_fill_bulk_urb(port->write_urb, port->serial->dev,
669 usb_sndbulkpipe(port->serial->dev,
670 port->bulk_out_endpointAddress),
671 port->write_urb->transfer_buffer, priv->writelen + 3,
672 iuu_rxcmd, port);
673 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
674 spin_lock_irqsave(&priv->lock, flags);
675 priv->writelen = 0;
676 spin_unlock_irqrestore(&priv->lock, flags);
677 usb_serial_port_softint(port);
678 return result;
679}
680
681static int iuu_read_buf(struct usb_serial_port *port, int len)
682{
683 int result;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800684 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200685
686 usb_fill_bulk_urb(port->read_urb, port->serial->dev,
687 usb_rcvbulkpipe(port->serial->dev,
688 port->bulk_in_endpointAddress),
689 port->read_urb->transfer_buffer, len,
690 read_buf_callback, port);
691 result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
692 return result;
693}
694
695static void iuu_uart_read_callback(struct urb *urb)
696{
Ming Leicdc97792008-02-24 18:41:47 +0800697 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200698 struct iuu_private *priv = usb_get_serial_port_data(port);
Steven Rostedt85943032008-05-06 20:42:31 -0700699 unsigned long flags;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200700 int status;
701 int error = 0;
702 int len = 0;
703 unsigned char *data = urb->transfer_buffer;
704 priv->poll++;
705
Harvey Harrison441b62c2008-03-03 16:08:34 -0800706 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200707
708 if (urb->status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800709 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200710 /* error stop all */
711 return;
712 }
713 if (data == NULL)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800714 dbg("%s - data is NULL !!!", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200715
716 if (urb->actual_length == 1 && data != NULL)
717 len = (int) data[0];
718
719 if (urb->actual_length > 1) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800720 dbg("%s - urb->actual_length = %i", __func__,
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200721 urb->actual_length);
722 error = 1;
723 return;
724 }
725 /* if len > 0 call readbuf */
726
727 if (len > 0 && error == 0) {
728 dbg("%s - call read buf - len to read is %i ",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800729 __func__, len);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200730 status = iuu_read_buf(port, len);
731 return;
732 }
733 /* need to update status ? */
734 if (priv->poll > 99) {
735 status = iuu_status(port);
736 priv->poll = 0;
737 return;
738 }
739
740 /* reset waiting ? */
741
742 if (priv->reset == 1) {
743 status = iuu_reset(port, 0xC);
744 return;
745 }
746 /* Writebuf is waiting */
747 spin_lock_irqsave(&priv->lock, flags);
748 if (priv->writelen > 0) {
749 spin_unlock_irqrestore(&priv->lock, flags);
750 status = iuu_bulk_write(port);
751 return;
752 }
753 spin_unlock_irqrestore(&priv->lock, flags);
754 /* if nothing to write call again rxcmd */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800755 dbg("%s - rxcmd recall", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200756 iuu_led_activity_off(urb);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200757}
758
Alan Cox95da3102008-07-22 11:09:07 +0100759static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
760 const u8 *buf, int count)
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200761{
762 struct iuu_private *priv = usb_get_serial_port_data(port);
Steven Rostedt85943032008-05-06 20:42:31 -0700763 unsigned long flags;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800764 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200765
766 if (count > 256)
767 return -ENOMEM;
768
769 spin_lock_irqsave(&priv->lock, flags);
770 if (priv->writelen > 0) {
771 /* buffer already filled but not commited */
772 spin_unlock_irqrestore(&priv->lock, flags);
773 return (0);
774 }
775 /* fill the buffer */
776 memcpy(priv->writebuf, buf, count);
777 priv->writelen = count;
778 spin_unlock_irqrestore(&priv->lock, flags);
779
780 return (count);
781}
782
783static void read_rxcmd_callback(struct urb *urb)
784{
Ming Leicdc97792008-02-24 18:41:47 +0800785 struct usb_serial_port *port = urb->context;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200786 int result;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800787 dbg("%s - enter", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200788
Harvey Harrison441b62c2008-03-03 16:08:34 -0800789 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200790
791 if (urb->status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800792 dbg("%s - urb->status = %d", __func__, urb->status);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200793 /* error stop all */
794 return;
795 }
796
797 usb_fill_bulk_urb(port->read_urb, port->serial->dev,
798 usb_rcvbulkpipe(port->serial->dev,
799 port->bulk_in_endpointAddress),
800 port->read_urb->transfer_buffer, 256,
801 iuu_uart_read_callback, port);
802 result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
Harvey Harrison441b62c2008-03-03 16:08:34 -0800803 dbg("%s - submit result = %d", __func__, result);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200804 return;
805}
806
807static int iuu_uart_on(struct usb_serial_port *port)
808{
809 int status;
810 u8 *buf;
811
812 buf = kmalloc(sizeof(u8) * 4, GFP_KERNEL);
813
814 if (!buf)
815 return -ENOMEM;
816
817 buf[0] = IUU_UART_ENABLE;
818 buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF);
819 buf[2] = (u8) (0x00FF & IUU_BAUD_9600);
820 buf[3] = (u8) (0x0F0 & IUU_TWO_STOP_BITS) | (0x07 & IUU_PARITY_EVEN);
821
822 status = bulk_immediate(port, buf, 4);
823 if (status != IUU_OPERATION_OK) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800824 dbg("%s - uart_on error", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200825 goto uart_enable_failed;
826 }
827 /* iuu_reset() the card after iuu_uart_on() */
828 status = iuu_uart_flush(port);
829 if (status != IUU_OPERATION_OK)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800830 dbg("%s - uart_flush error", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200831uart_enable_failed:
832 kfree(buf);
833 return status;
834}
835
836/* Diables the IUU UART (a.k.a. the Phoenix voiderface) */
837static int iuu_uart_off(struct usb_serial_port *port)
838{
839 int status;
840 u8 *buf;
841 buf = kmalloc(1, GFP_KERNEL);
842 if (!buf)
843 return -ENOMEM;
844 buf[0] = IUU_UART_DISABLE;
845
846 status = bulk_immediate(port, buf, 1);
847 if (status != IUU_OPERATION_OK)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800848 dbg("%s - uart_off error", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200849
850 kfree(buf);
851 return status;
852}
853
854static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
855 u32 *actual, u8 parity)
856{
857 int status;
858 u8 *dataout;
859 u8 DataCount = 0;
860 u8 T1Frekvens = 0;
861 u8 T1reload = 0;
862 unsigned int T1FrekvensHZ = 0;
863
864 dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
865
866 if (!dataout)
867 return -ENOMEM;
868
869 if (baud < 1200 || baud > 230400) {
870 kfree(dataout);
871 return IUU_INVALID_PARAMETER;
872 }
873 if (baud > 977) {
874 T1Frekvens = 3;
875 T1FrekvensHZ = 500000;
876 }
877
878 if (baud > 3906) {
879 T1Frekvens = 2;
880 T1FrekvensHZ = 2000000;
881 }
882
883 if (baud > 11718) {
884 T1Frekvens = 1;
885 T1FrekvensHZ = 6000000;
886 }
887
888 if (baud > 46875) {
889 T1Frekvens = 0;
890 T1FrekvensHZ = 24000000;
891 }
892
893 T1reload = 256 - (u8) (T1FrekvensHZ / (baud * 2));
894
895 /* magic number here: ENTER_FIRMWARE_UPDATE; */
896 dataout[DataCount++] = IUU_UART_ESC;
897 /* magic number here: CHANGE_BAUD; */
898 dataout[DataCount++] = IUU_UART_CHANGE;
899 dataout[DataCount++] = T1Frekvens;
900 dataout[DataCount++] = T1reload;
901
902 *actual = (T1FrekvensHZ / (256 - T1reload)) / 2;
903
904 switch (parity & 0x0F) {
905 case IUU_PARITY_NONE:
906 dataout[DataCount++] = 0x00;
907 break;
908 case IUU_PARITY_EVEN:
909 dataout[DataCount++] = 0x01;
910 break;
911 case IUU_PARITY_ODD:
912 dataout[DataCount++] = 0x02;
913 break;
914 case IUU_PARITY_MARK:
915 dataout[DataCount++] = 0x03;
916 break;
917 case IUU_PARITY_SPACE:
918 dataout[DataCount++] = 0x04;
919 break;
920 default:
921 kfree(dataout);
922 return IUU_INVALID_PARAMETER;
923 break;
924 }
925
926 switch (parity & 0xF0) {
927 case IUU_ONE_STOP_BIT:
928 dataout[DataCount - 1] |= IUU_ONE_STOP_BIT;
929 break;
930
931 case IUU_TWO_STOP_BITS:
932 dataout[DataCount - 1] |= IUU_TWO_STOP_BITS;
933 break;
934 default:
935 kfree(dataout);
936 return IUU_INVALID_PARAMETER;
937 break;
938 }
939
940 status = bulk_immediate(port, dataout, DataCount);
941 if (status != IUU_OPERATION_OK)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800942 dbg("%s - uart_off error", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200943 kfree(dataout);
944 return status;
945}
946
947static int set_control_lines(struct usb_device *dev, u8 value)
948{
949 return 0;
950}
951
Alan Cox95da3102008-07-22 11:09:07 +0100952static void iuu_close(struct tty_struct *tty,
953 struct usb_serial_port *port, struct file *filp)
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200954{
955 /* iuu_led (port,255,0,0,0); */
956 struct usb_serial *serial;
957 struct iuu_private *priv = usb_get_serial_port_data(port);
958 unsigned long flags;
959 unsigned int c_cflag;
960
961 serial = port->serial;
962 if (!serial)
963 return;
964
Harvey Harrison441b62c2008-03-03 16:08:34 -0800965 dbg("%s - port %d", __func__, port->number);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200966
967 iuu_uart_off(port);
968 if (serial->dev) {
Alan Cox95da3102008-07-22 11:09:07 +0100969 if (tty) {
970 c_cflag = tty->termios->c_cflag;
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200971 if (c_cflag & HUPCL) {
972 /* drop DTR and RTS */
973 priv = usb_get_serial_port_data(port);
974 spin_lock_irqsave(&priv->lock, flags);
975 priv->line_control = 0;
976 spin_unlock_irqrestore(&priv->lock, flags);
977 set_control_lines(port->serial->dev, 0);
978 }
979 }
980 /* free writebuf */
981 /* shutdown our urbs */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800982 dbg("%s - shutting down urbs", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200983 usb_kill_urb(port->write_urb);
984 usb_kill_urb(port->read_urb);
985 usb_kill_urb(port->interrupt_in_urb);
986 msleep(1000);
987 /* wait one second to free all buffers */
988 iuu_led(port, 0, 0, 0xF000, 0xFF);
989 msleep(1000);
990 usb_reset_device(port->serial->dev);
991 }
992}
993
Alan Cox95da3102008-07-22 11:09:07 +0100994static int iuu_open(struct tty_struct *tty,
995 struct usb_serial_port *port, struct file *filp)
Alain Degreffe60a8fc02007-10-26 13:51:49 +0200996{
997 struct usb_serial *serial = port->serial;
998 u8 *buf;
999 int result;
1000 u32 actual;
1001 unsigned long flags;
1002 struct iuu_private *priv = usb_get_serial_port_data(port);
1003
Harvey Harrison441b62c2008-03-03 16:08:34 -08001004 dbg("%s - port %d", __func__, port->number);
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001005 usb_clear_halt(serial->dev, port->write_urb->pipe);
1006 usb_clear_halt(serial->dev, port->read_urb->pipe);
1007
1008 buf = kmalloc(10, GFP_KERNEL);
1009 if (buf == NULL)
1010 return -ENOMEM;
1011
1012 /* fixup the endpoint buffer size */
1013 kfree(port->bulk_out_buffer);
1014 port->bulk_out_buffer = kmalloc(512, GFP_KERNEL);
1015 port->bulk_out_size = 512;
1016 kfree(port->bulk_in_buffer);
1017 port->bulk_in_buffer = kmalloc(512, GFP_KERNEL);
1018 port->bulk_in_size = 512;
1019
1020 if (!port->bulk_out_buffer || !port->bulk_in_buffer) {
1021 kfree(port->bulk_out_buffer);
1022 kfree(port->bulk_in_buffer);
1023 kfree(buf);
1024 return -ENOMEM;
1025 }
1026
1027 usb_fill_bulk_urb(port->write_urb, port->serial->dev,
1028 usb_sndbulkpipe(port->serial->dev,
1029 port->bulk_out_endpointAddress),
1030 port->bulk_out_buffer, 512,
1031 NULL, NULL);
1032
1033
1034 usb_fill_bulk_urb(port->read_urb, port->serial->dev,
1035 usb_rcvbulkpipe(port->serial->dev,
1036 port->bulk_in_endpointAddress),
1037 port->bulk_in_buffer, 512,
1038 NULL, NULL);
1039
1040 /* set the termios structure */
1041 spin_lock_irqsave(&priv->lock, flags);
Alan Cox95da3102008-07-22 11:09:07 +01001042 if (tty && !priv->termios_initialized) {
1043 *(tty->termios) = tty_std_termios;
1044 tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
1045 | TIOCM_CTS | CSTOPB | PARENB;
1046 tty->termios->c_ispeed = 9600;
1047 tty->termios->c_ospeed = 9600;
1048 tty->termios->c_lflag = 0;
1049 tty->termios->c_oflag = 0;
1050 tty->termios->c_iflag = 0;
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001051 priv->termios_initialized = 1;
Alan Cox95da3102008-07-22 11:09:07 +01001052 tty->low_latency = 1;
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001053 priv->poll = 0;
1054 }
1055 spin_unlock_irqrestore(&priv->lock, flags);
1056
1057 /* initialize writebuf */
1058#define FISH(a, b, c, d) do { \
1059 result = usb_control_msg(port->serial->dev, \
1060 usb_rcvctrlpipe(port->serial->dev, 0), \
1061 b, a, c, d, buf, 1, 1000); \
1062 dbg("0x%x:0x%x:0x%x:0x%x %d - %x", a, b, c, d, result, \
1063 buf[0]); } while (0);
1064
1065#define SOUP(a, b, c, d) do { \
1066 result = usb_control_msg(port->serial->dev, \
1067 usb_sndctrlpipe(port->serial->dev, 0), \
1068 b, a, c, d, NULL, 0, 1000); \
1069 dbg("0x%x:0x%x:0x%x:0x%x %d", a, b, c, d, result); } while (0)
1070
1071 /* This is not UART related but IUU USB driver related or something */
1072 /* like that. Basically no IUU will accept any commands from the USB */
1073 /* host unless it has received the following message */
1074 /* sprintf(buf ,"%c%c%c%c",0x03,0x02,0x02,0x0); */
1075
1076 SOUP(0x03, 0x02, 0x02, 0x0);
1077 kfree(buf);
1078 iuu_led(port, 0xF000, 0xF000, 0, 0xFF);
1079 iuu_uart_on(port);
1080 if (boost < 100)
1081 boost = 100;
1082 switch (clockmode) {
1083 case 2: /* 3.680 Mhz */
1084 iuu_clk(port, IUU_CLK_3680000 * boost / 100);
1085 result =
1086 iuu_uart_baud(port, 9600 * boost / 100, &actual,
1087 IUU_PARITY_EVEN);
1088 break;
1089 case 3: /* 6.00 Mhz */
1090 iuu_clk(port, IUU_CLK_6000000 * boost / 100);
1091 result =
1092 iuu_uart_baud(port, 16457 * boost / 100, &actual,
1093 IUU_PARITY_EVEN);
1094 break;
1095 default: /* 3.579 Mhz */
1096 iuu_clk(port, IUU_CLK_3579000 * boost / 100);
1097 result =
1098 iuu_uart_baud(port, 9600 * boost / 100, &actual,
1099 IUU_PARITY_EVEN);
1100 }
1101
1102 /* set the cardin cardout signals */
1103 switch (cdmode) {
1104 case 0:
1105 iuu_cardin = 0;
1106 iuu_cardout = 0;
1107 break;
1108 case 1:
1109 iuu_cardin = TIOCM_CD;
1110 iuu_cardout = 0;
1111 break;
1112 case 2:
1113 iuu_cardin = 0;
1114 iuu_cardout = TIOCM_CD;
1115 break;
1116 case 3:
1117 iuu_cardin = TIOCM_DSR;
1118 iuu_cardout = 0;
1119 break;
1120 case 4:
1121 iuu_cardin = 0;
1122 iuu_cardout = TIOCM_DSR;
1123 break;
1124 case 5:
1125 iuu_cardin = TIOCM_CTS;
1126 iuu_cardout = 0;
1127 break;
1128 case 6:
1129 iuu_cardin = 0;
1130 iuu_cardout = TIOCM_CTS;
1131 break;
1132 case 7:
1133 iuu_cardin = TIOCM_RNG;
1134 iuu_cardout = 0;
1135 break;
1136 case 8:
1137 iuu_cardin = 0;
1138 iuu_cardout = TIOCM_RNG;
1139 }
1140
1141 iuu_uart_flush(port);
1142
Harvey Harrison441b62c2008-03-03 16:08:34 -08001143 dbg("%s - initialization done", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001144
1145 memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
1146 usb_fill_bulk_urb(port->write_urb, port->serial->dev,
1147 usb_sndbulkpipe(port->serial->dev,
1148 port->bulk_out_endpointAddress),
1149 port->write_urb->transfer_buffer, 1,
1150 read_rxcmd_callback, port);
1151 result = usb_submit_urb(port->write_urb, GFP_KERNEL);
1152
1153 if (result) {
1154 dev_err(&port->dev, "%s - failed submitting read urb,"
Harvey Harrison441b62c2008-03-03 16:08:34 -08001155 " error %d\n", __func__, result);
Alan Cox95da3102008-07-22 11:09:07 +01001156 iuu_close(tty, port, NULL);
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001157 return -EPROTO;
1158 } else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001159 dbg("%s - rxcmd OK", __func__);
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001160 }
1161 return result;
1162}
1163
1164static struct usb_serial_driver iuu_device = {
1165 .driver = {
1166 .owner = THIS_MODULE,
1167 .name = "iuu_phoenix",
1168 },
1169 .id_table = id_table,
Alain Degreffe60a8fc02007-10-26 13:51:49 +02001170 .num_ports = 1,
1171 .open = iuu_open,
1172 .close = iuu_close,
1173 .write = iuu_uart_write,
1174 .read_bulk_callback = iuu_uart_read_callback,
1175 .tiocmget = iuu_tiocmget,
1176 .tiocmset = iuu_tiocmset,
1177 .attach = iuu_startup,
1178 .shutdown = iuu_shutdown,
1179};
1180
1181static int __init iuu_init(void)
1182{
1183 int retval;
1184 retval = usb_serial_register(&iuu_device);
1185 if (retval)
1186 goto failed_usb_serial_register;
1187 retval = usb_register(&iuu_driver);
1188 if (retval)
1189 goto failed_usb_register;
1190 info(DRIVER_DESC " " DRIVER_VERSION);
1191 return 0;
1192failed_usb_register:
1193 usb_serial_deregister(&iuu_device);
1194failed_usb_serial_register:
1195 return retval;
1196}
1197
1198static void __exit iuu_exit(void)
1199{
1200 usb_deregister(&iuu_driver);
1201 usb_serial_deregister(&iuu_device);
1202}
1203
1204module_init(iuu_init);
1205module_exit(iuu_exit);
1206
1207MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
1208
1209MODULE_DESCRIPTION(DRIVER_DESC);
1210MODULE_LICENSE("GPL");
1211
1212MODULE_VERSION(DRIVER_VERSION);
1213module_param(debug, bool, S_IRUGO | S_IWUSR);
1214MODULE_PARM_DESC(debug, "Debug enabled or not");
1215
1216module_param(xmas, bool, S_IRUGO | S_IWUSR);
1217MODULE_PARM_DESC(xmas, "xmas color enabled or not");
1218
1219module_param(boost, int, S_IRUGO | S_IWUSR);
1220MODULE_PARM_DESC(boost, "overclock boost percent 100 to 500");
1221
1222module_param(clockmode, int, S_IRUGO | S_IWUSR);
1223MODULE_PARM_DESC(clockmode, "1=3Mhz579,2=3Mhz680,3=6Mhz");
1224
1225module_param(cdmode, int, S_IRUGO | S_IWUSR);
1226MODULE_PARM_DESC(cdmode, "Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, "
1227 "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING");