English Language flag
// Log In
// CVSweb
Project: FreeWRT
// Summary // Activity // Search // Tracker // Lists // News // SCM // Wiki

SCM Repository

ViewVC logotype

Contents of /branches/freewrt_1_0/target/linux/brcm-2.4/patches/009-hso.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3786 - (show annotations) (download)
Fri Aug 22 14:36:38 2008 UTC (5 years, 6 months ago) by markus
File size: 85431 byte(s)
added hso driver backport (see www.pharscape.org) to support Option HSUPA cards. Some comgt-scripts will come next.
1 diff --exclude=CVS -Nur linux-2.4.36.6.orig/drivers/char/pcmcia/hso/hso.c linux-2.4.36.6/drivers/char/pcmcia/hso/hso.c
2 --- linux-2.4.36.6.orig/drivers/char/pcmcia/hso/hso.c 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.4.36.6/drivers/char/pcmcia/hso/hso.c 2008-07-30 12:43:00.000000000 +0200
4 @@ -0,0 +1,3092 @@
5 +/*
6 + * Driver for Option High Speed Mobile Devices.
7 + *
8 + * Copyright (C) 2007 Option International
9 + * Copyright (C) 2007 Andrew Bird (Sphere Systems Ltd) ajb@spheresystems.co.uk
10 + *
11 + * This program is free software; you can redistribute it and/or modify
12 + * it under the terms of the GNU General Public License version 2 as
13 + * published by the Free Software Foundation.
14 + *
15 + * This program is distributed in the hope that it will be useful,
16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 + * GNU General Public License for more details.
19 + *
20 + * You should have received a copy of the GNU General Public License
21 + * along with this program; if not, write to the Free Software
22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 + *
24 + * 0.1 Option International
25 + * 2.4 driver
26 + * 0.2 Andrew Bird (Sphere Systems Ltd)
27 + * Initial port to 2.6, target 2.6.21/22
28 + * 0.3 Andrew Bird (Sphere Systems Ltd)
29 + * Multiple device support, startup & shutdown cleanups
30 + * 0.4 Andrew Bird (Sphere Systems Ltd)
31 + * Initial support for Circuit Switched interface - no H/W handshaking
32 + * 0.5 Filip Aben ( Option )
33 + * - Removed internal project names from comments
34 + * - Removed dependency on Modem port which is not always there
35 + * - Added USB id's for other compatible Option devices
36 + * 0.6 Marco Himmer ( Option )
37 + * - Send REZERO UNIT command to switch from UMS to 3G device
38 + * - Move packed out of struct to avoid compiler warning
39 + * 0.7 Filip Aben
40 + * - Added 2.6.12+ compatability
41 + * 0.7-2.4 Andrew Bird (Sphere Systems Ltd)
42 + * - Added 2.4 compatibility - eek!
43 + *
44 + */
45 +
46 +#include <linux/sched.h>
47 +#include <linux/slab.h>
48 +#include <linux/init.h>
49 +#include <linux/delay.h>
50 +#include <linux/netdevice.h>
51 +#include <linux/inetdevice.h>
52 +#include <linux/etherdevice.h>
53 +#include <linux/module.h>
54 +#include <linux/ethtool.h>
55 +#include <asm/uaccess.h>
56 +
57 +#include <linux/usb.h>
58 +#include <linux/timer.h>
59 +
60 +#include <linux/tty.h>
61 +#include <linux/tty_driver.h>
62 +#include <linux/tty_flip.h>
63 +#include <linux/kmod.h>
64 +
65 +#include <asm/byteorder.h>
66 +#include <linux/version.h>
67 +
68 +/* #define DEBUG */
69 +#define HSO_PROC
70 +
71 +#ifdef HSO_PROC
72 +#include <linux/proc_fs.h>
73 +#endif
74 +
75 +#include <net/arp.h>
76 +#include <linux/ip.h>
77 +
78 +/*
79 + Description of the device:
80 +
81 + Interface 0: Contains the IP network interface on the bulk end points.
82 + The multiplexed serial ports are using the interrupt and control endpoints.
83 + Interrupt contains a bitmap telling which multiplexed serialport needs servicing.
84 +
85 + Interface 1: Diagnostics port, uses bulk only, do not submit urbs until the port is opened, as
86 + this have a huge impact on the network port throughput.
87 +
88 + Interface 2: Standard modem interface - circuit switched interface, should not be used.
89 + */
90 +
91 +#define DRIVER_VERSION "0.7"
92 +#define MOD_AUTHOR "Option Wireless"
93 +
94 +/* From CDC Spec Table 24 */
95 +#define CS_INTERFACE_VAL 0x24
96 +
97 +#define HSO__MAX_MTU 1984 /*1536 */
98 +#define DEFAULT_MTU 1500
99 +#define DEFAULT_MRU 1500
100 +
101 +#define CTRL_URB_RX_SIZE 1024
102 +#define CTRL_URB_TX_SIZE 64
103 +
104 +#define BULK_URB_RX_SIZE 4096
105 +#define BULK_URB_TX_SIZE 8192
106 +
107 +#define MUX_INTR_BUF_SIZE 16
108 +#define MUX_BULK_RX_BUF_SIZE HSO__MAX_MTU
109 +#define MUX_BULK_TX_BUF_SIZE HSO__MAX_MTU
110 +#define MUX_BULK_RX_BUF_COUNT 4
111 +#define USB_TYPE_OPTION_VENDOR 0x20
112 +
113 +/* These definitions are used with the struct hso_priv flags element
114 + - use *_bit operations on it. (bit indices not values.)*/
115 +#define HSO_NET_RUNNING 0
116 +#define HSO_NET_TX_BUSY 1
117 +#define HSO_CARD_UNPLUG 2
118 +
119 +#define HSO_NET_TX_TIMEOUT (HZ*10)
120 +
121 +#define SEND_ENCAPSULATED_COMMAND 0x00
122 +#define GET_ENCAPSULATED_RESPONSE 0x01
123 +
124 +/* Serial port defines and structs. */
125 +#define HSO_THRESHOLD_THROTTLE (7*1024)
126 +#define HSO_THRESHOLD_UNTHROTTLE (2*1024)
127 +
128 +/* These definitions used in the Ethernet Packet Filtering requests */
129 +/* See CDC Spec Table 62 */
130 +#define MODE_FLAG_PROMISCUOUS (1<<0)
131 +#define MODE_FLAG_ALL_MULTICAST (1<<1)
132 +#define MODE_FLAG_DIRECTED (1<<2)
133 +#define MODE_FLAG_BROADCAST (1<<3)
134 +#define MODE_FLAG_MULTICAST (1<<4)
135 +
136 +/* CDC Spec class requests - CDC Spec Table 46 */
137 +#define SET_ETHERNET_MULTICAST_FILTER 0x40
138 +#define SET_ETHERNET_PACKET_FILTER 0x43
139 +
140 +#define HSO_SERIAL_FLAG_THROTTLED 0
141 +#define HSO_SERIAL_FLAG_TX_SENT 1
142 +#define HSO_SERIAL_FLAG_RX_SENT 2
143 +
144 +#define HSO_SERIAL_TTY_MAJOR 245 /* Experimental Major. */
145 +#define HSO_SERIAL_MAGIC 0x48534f31
146 +
147 +/* Variables and such */
148 +#define HSO_SERIAL_TTY_MINORS 256 /* Number of ttys to handle */
149 +
150 +#define D__(lvl_, fmt, arg...) do { \
151 +printk(lvl_ "[%d:%s]: " fmt "\n", __LINE__, __FUNCTION__, ## arg); } while(0)
152 +
153 +#define NFO(args...) D__( KERN_INFO, ##args)
154 +#define ERR(args...) D__( KERN_ERR, ##args)
155 +#define WARN(args...) D__( KERN_WARNING, ##args)
156 +
157 +#define D_(lvl, args...) do { if(lvl & debug) NFO( args ); } while(0)
158 +
159 +#define D1(args...) D_(0x01, ##args)
160 +#define D2(args...) D_(0x02, ##args)
161 +#define D3(args...) D_(0x04, ##args)
162 +#define D4(args...) D_(0x08, ##args)
163 +#define D5(args...) D_(0x10, ##args)
164 +#define D D1
165 +
166 +#define QFO(fmt, args...) do { \
167 + printk( KERN_INFO "hso: " fmt "\n", ##args); \
168 +} while(0)
169 +
170 +#if 0
171 +#define DUMP(buf_, len_) \
172 +do { \
173 + char info_[256]; \
174 + u8 i_, count_=0; \
175 + for(i_=0;i_<len_;i_++) { \
176 + count_ += snprintf(info_+count_, sizeof(info_)-count_, "%02x ", ((u8*)buf_)[i_]); \
177 + if (i_!= 0 && (i_ % 35) == 0) { count_ += snprintf(info_+count_, sizeof(info_)-count_,"\n");} \
178 + } \
179 + \
180 + if (len_) { \
181 + NFO("%d: dump[%s]", len_, info_); \
182 + } \
183 +} while (0)
184 +#endif
185 +
186 +
187 +
188 +#ifdef DEBUG
189 +static void dbg_dump(int line_count, const char *func_name, unsigned char *buf,
190 + unsigned int len)
191 +{
192 + u8 i = 0;
193 +
194 + printk("[%d:%s]: len %d", line_count, func_name, len);
195 +
196 + for (i = 0; i < len; i++) {
197 + if (!(i % 16))
198 + printk("\n 0x%03x: ", i);
199 + printk("%02x ", (unsigned char)buf[i]);
200 + }
201 + printk("\n");
202 +}
203 +#define DUMP(buf_, len_) dbg_dump(__LINE__, __FUNCTION__, buf_, len_)
204 +#define DUMP1(buf_, len_) do{ if(0x01 & debug) DUMP(buf_, len_);}while(0)
205 +#endif
206 +
207 +enum type_intf {
208 + MUX_INTERFACE,
209 + QXDM_INTERFACE,
210 + CS_INTERFACE
211 +};
212 +
213 +enum pkt_parse_state {
214 + WAIT_IP,
215 + WAIT_DATA,
216 + WAIT_SYNC
217 +};
218 +
219 +struct option_descriptor {
220 + u8 length;
221 + u8 descriptor_type;
222 + u8 enabled_ports;
223 +} __attribute__ ((packed)) ;
224 +
225 +struct hso_priv {
226 + struct net_device_stats stats;
227 + struct net_device *net;
228 + struct usb_device *usb;
229 + struct option_descriptor option_info;
230 + unsigned long flags;
231 + u32 properties;
232 +
233 + struct proc_dir_entry *ourproc;
234 +
235 + int mux_ep_intr;
236 + int mux_ep_intr_size;
237 + void *mux_intr_buf;
238 + struct urb *mux_intr_urb;
239 +
240 + int mux_ep_bulk_in;
241 + int mux_ep_bulk_out;
242 + int mux_ep_bulk_out_size;
243 + int mux_ep_bulk_in_size;
244 + int mux_bInterval;
245 + struct urb *mux_bulk_rx_urb_pool[MUX_BULK_RX_BUF_COUNT];
246 + struct urb *mux_bulk_tx_urb;
247 + void *mux_bulk_rx_buf_pool[MUX_BULK_RX_BUF_COUNT];
248 + void *mux_bulk_tx_buf;
249 +
250 + spinlock_t net_lock;
251 + struct sk_buff *skb_rx_buf;
252 + enum pkt_parse_state rx_parse_state;
253 + unsigned short rx_buf_size, rx_buf_missing;
254 + struct iphdr rx_ip_hdr;
255 + struct ethhdr dummy_eth_head;
256 +
257 + __u16 bcdCDC;
258 + __u16 wMaxSegmentSize;
259 + __u16 wNumberMCFilters;
260 + __u16 mode_flags;
261 +
262 +/* struct usb_ctrlrequest ctrl_req; */
263 +};
264 +
265 +struct hso_serial {
266 + int magic;
267 + u8 minor;
268 + u8 mux;
269 + enum type_intf type;
270 + struct hso_priv *odev;
271 +
272 + /* rx/tx urb could be either a bulk urb or a control urb depending
273 + on which serial port it is used on. */
274 + struct urb *rx_urb;
275 + u8 *rx_data;
276 + u16 rx_data_length; /* should contain allocated length */
277 +
278 + struct urb *tx_urb;
279 + u8 *tx_data;
280 + u16 tx_data_length; /* should contain allocated length */
281 + u16 tx_data_count;
282 + struct usb_ctrlrequest ctrl_req_tx;
283 + struct usb_ctrlrequest ctrl_req_rx;
284 +
285 + int ep_bulk_in; /* for standard ports, not muxed ones */
286 + int ep_bulk_out;
287 + int ep_bulk_out_size;
288 + int ep_bulk_in_size;
289 +
290 + unsigned long flags;
291 +
292 + int (*write_data) (struct hso_serial *serial);
293 +
294 + /* from usb_serial_port */
295 + struct tty_struct *tty;
296 + int open_count;
297 + struct semaphore sem;
298 + void *private;
299 +};
300 +
301 +/*
302 + Globals
303 + */
304 +static int debug = 0x00;
305 +
306 +static const char driver_name[] = "hso";
307 +static const char *version = __FILE__ ": " DRIVER_VERSION " " MOD_AUTHOR;
308 +
309 +static struct tty_driver *tty_drv;
310 +
311 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) )
312 +static int hso_serial_refcount;
313 +static struct tty_struct *hso_serial_tty[HSO_SERIAL_TTY_MINORS];
314 +#endif
315 +
316 +static struct hso_serial *serial_table[HSO_SERIAL_TTY_MINORS];
317 +static spinlock_t serial_table_lock;
318 +
319 +static struct proc_dir_entry *hso_proc_dir;
320 +static struct proc_dir_entry *hso_proc_dir_devices;
321 +
322 +static struct usb_driver hso_driver;
323 +
324 +static struct usb_device_id hso_ids[] = {
325 +
326 + {.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT | USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL, .idVendor = 0x0af0, .idProduct = 0x1000, .bInterfaceClass = 8, .bInterfaceSubClass = 6, .bInterfaceProtocol = 80},
327 + {USB_DEVICE(0x0af0, 0x6711)},
328 + {USB_DEVICE(0x0af0, 0x6731)},
329 + {USB_DEVICE(0x0af0, 0x6751)},
330 + {USB_DEVICE(0x0af0, 0x6771)},
331 + {USB_DEVICE(0x0af0, 0x6791)},
332 + {USB_DEVICE(0x0af0, 0x6811)},
333 + {USB_DEVICE(0x0af0, 0x6911)},
334 + {USB_DEVICE(0x0af0, 0x6951)},
335 + {USB_DEVICE(0x0af0, 0x6971)},
336 + {USB_DEVICE(0x0af0, 0x7011)},
337 + {USB_DEVICE(0x0af0, 0x7031)},
338 + {USB_DEVICE(0x0af0, 0x7051)},
339 + {USB_DEVICE(0x0af0, 0x7071)},
340 + {USB_DEVICE(0x0af0, 0x7111)},
341 + {USB_DEVICE(0x0af0, 0x7211)},
342 + {USB_DEVICE(0x0af0, 0x7251)},
343 + {USB_DEVICE(0x0af0, 0x7271)},
344 + {USB_DEVICE(0x0af0, 0x7311)},
345 + {}
346 +};
347 +
348 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
349 +static struct termios *hso_serial_termios[HSO_SERIAL_TTY_MINORS];
350 +static struct termios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS];
351 +#else
352 +static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS];
353 +static struct ktermios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS];
354 +#endif
355 +
356 +/*
357 + * Prototypes
358 + */
359 +static struct hso_serial *hso_serial_start(struct hso_priv *odev, u8 minor,
360 + enum type_intf type, u8 num);
361 +
362 +static void hso_serial_stop(struct usb_device *dev, u8 minor, struct hso_priv *odev);
363 +
364 +static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial);
365 +
366 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
367 +static void _hso_serial_set_termios(struct tty_struct *tty,
368 + struct termios *old);
369 +#else
370 +static void _hso_serial_set_termios(struct tty_struct *tty,
371 + struct ktermios *old);
372 +#endif
373 +
374 +static void hso_serial_disconnect(struct usb_device *usb, struct hso_priv *odev);
375 +
376 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
377 +static int hso_mux_submit_intr_urb(struct hso_priv *odev,int gfp);
378 +#else
379 +static int hso_mux_submit_intr_urb(struct hso_priv *odev,gfp_t gfp);
380 +#endif
381 +
382 +static int hso_mux_serial_read(struct hso_priv *odev, struct hso_serial *serial);
383 +
384 +/*
385 + * Function declarations
386 + */
387 +
388 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) )
389 +
390 +#define URB_ZERO_PACKET USB_ZERO_PACKET
391 +
392 +static inline void *kzalloc(size_t size, int gfp)
393 +{
394 + void *p = kmalloc(size, gfp);
395 + if(p)
396 + memset(p, 0, size);
397 + return p;
398 +}
399 +
400 +#define netdev_priv(x) x->priv
401 +
402 +static inline void *usb_get_intfdata (struct usb_interface *intf)
403 +{
404 + return intf->private_data;
405 +}
406 +
407 +static inline void usb_set_intfdata (struct usb_interface *intf, void *data)
408 +{
409 + intf->private_data=data;
410 +}
411 +
412 +#else
413 +#define kzalloc(x,y) kcalloc(x,1,y)
414 +#endif
415 +
416 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
417 +
418 +/* Following functions are copied straight from the 2.6.20 kernel to maintain compatability */
419 +
420 +static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
421 +{
422 + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
423 + USB_ENDPOINT_XFER_BULK);
424 +}
425 +
426 +static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
427 +{
428 + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
429 +}
430 +
431 +static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
432 +{
433 + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
434 +}
435 +
436 +static inline int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
437 +{
438 + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
439 +}
440 +
441 +static inline int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
442 +{
443 + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
444 +}
445 +
446 +#endif
447 +
448 +static int get_free_serial_index(void)
449 +{
450 + int index;
451 + unsigned long flags;
452 +
453 + spin_lock_irqsave(&serial_table_lock,flags);
454 +
455 + for(index = 0;index < HSO_SERIAL_TTY_MINORS;index++) {
456 + if( serial_table[index] == NULL ) {
457 + spin_unlock_irqrestore(&serial_table_lock,flags);
458 + return index;
459 + }
460 + }
461 +
462 + spin_unlock_irqrestore(&serial_table_lock,flags);
463 +
464 + ERR("no free serial devices in table");
465 +
466 + return -1;
467 +}
468 +
469 +static void set_serial_by_index(unsigned index,struct hso_serial *serial)
470 +{
471 + unsigned long flags;
472 +
473 + spin_lock_irqsave(&serial_table_lock,flags);
474 + serial_table[index] = serial;
475 + spin_unlock_irqrestore(&serial_table_lock,flags);
476 +}
477 +
478 +static struct hso_serial *get_serial_by_index(unsigned index)
479 +{
480 + struct hso_serial *serial;
481 + unsigned long flags;
482 +
483 + spin_lock_irqsave(&serial_table_lock,flags);
484 + serial = serial_table[index];
485 + spin_unlock_irqrestore(&serial_table_lock,flags);
486 +
487 + return serial;
488 +}
489 +
490 +static struct hso_serial *get_serial_by_odev_and_mux(struct hso_priv *odev,
491 + unsigned mux)
492 +{
493 + struct hso_serial *serial;
494 + int i;
495 + unsigned long flags;
496 +
497 + spin_lock_irqsave(&serial_table_lock,flags);
498 +
499 + for(i = 0;i < HSO_SERIAL_TTY_MINORS;i++) {
500 + if((serial = serial_table[i]) == NULL)
501 + continue;
502 +
503 + if(serial->odev == odev && serial->mux == mux) {
504 + spin_unlock_irqrestore(&serial_table_lock,flags);
505 + return serial;
506 + }
507 + }
508 +
509 + spin_unlock_irqrestore(&serial_table_lock,flags);
510 +
511 + return NULL;
512 +}
513 +
514 +/* returns serial struct and checks for validity of tty struct. */
515 +static inline struct hso_serial *get_serial_by_tty(struct tty_struct *tty)
516 +{
517 +
518 + if (tty == NULL || tty->driver_data == NULL) {
519 + return NULL;
520 + }
521 +
522 + return (struct hso_serial *) tty->driver_data;
523 +}
524 +
525 +/* global driver data */
526 +static int hso_proc_options(char *buf, char **start, off_t offset,
527 + int count, int *eof, void *data)
528 +{
529 + int len = 0;
530 +
531 + D1("count: %d", count);
532 +
533 + len += snprintf(buf + len, count - len, "debug: %02x\n", debug);
534 +
535 + return len;
536 +}
537 +
538 +/* per device instance data */
539 +static int hso_proc_device_ttys(char *buf, char **start, off_t offset,
540 + int count, int *eof, void *data)
541 +{
542 + int len = 0;
543 + int i;
544 + struct hso_serial *serial;
545 + unsigned long flags;
546 +
547 + D1("count: %d", count);
548 +
549 +
550 + spin_lock_irqsave(&serial_table_lock,flags);
551 +
552 + for(i = 0;i < HSO_SERIAL_TTY_MINORS;i++) {
553 + if((serial = serial_table[i]) == NULL)
554 + continue;
555 +
556 + if(serial->odev == data) {
557 + len += snprintf(buf + len, count - len, "/dev/%s%d\n",
558 + tty_drv->name, serial->minor);
559 + }
560 + }
561 +
562 + spin_unlock_irqrestore(&serial_table_lock,flags);
563 +
564 + return len;
565 +}
566 +
567 +/* TODO: make this a device variable */
568 +const unsigned char dummy_mac[6] = { 0, 1, 2, 3, 4, 5 };
569 +
570 +static void packetizeRx(struct hso_priv *odev, unsigned char *ip_pkt,
571 + unsigned int count)
572 +{
573 + unsigned short temp_bytes = 0, buffer_offset = 0, frame_len;
574 + unsigned char *tmp_rx_buf;
575 + struct ethhdr *eth_head;
576 +
577 +#ifdef DEBUG
578 + D("Rx %d bytes", count);
579 + DUMP(ip_pkt, min(128, count));
580 +#endif
581 +
582 + while (count) {
583 + switch (odev->rx_parse_state) {
584 + case WAIT_IP: /* waiting for IP header. */
585 + /* wanted bytes - size of ip header */
586 + temp_bytes =
587 + (count < odev->rx_buf_missing) ? count : odev->rx_buf_missing;
588 +
589 + memcpy(((unsigned char *)(&odev->rx_ip_hdr)) +
590 + odev->rx_buf_size, ip_pkt + buffer_offset,
591 + temp_bytes);
592 +
593 + odev->rx_buf_size += temp_bytes;
594 + buffer_offset += temp_bytes;
595 + odev->rx_buf_missing -= temp_bytes;
596 + count -= temp_bytes;
597 +
598 + if (!odev->rx_buf_missing) { /* header is complete allocate
599 + an sk_buffer and continue to WAIT_DATA */
600 + frame_len = ntohs(odev->rx_ip_hdr.tot_len);
601 +
602 + if (frame_len > DEFAULT_MRU) {
603 + odev->rx_parse_state = WAIT_SYNC;
604 + continue;
605 + }
606 + /* Allocate an sk_buff */
607 + if (!(odev->skb_rx_buf =
608 + dev_alloc_skb(frame_len + 2 +
609 + odev->net->hard_header_len))) {
610 + /* We got no receive buffer. */
611 + D("could not allocate memory");
612 + odev->rx_parse_state = WAIT_SYNC;
613 + return;
614 + }
615 + /* Here's where it came from */
616 + odev->skb_rx_buf->dev = odev->net;
617 +
618 + /* Make some headroom: standard alignment + the ethernet header. */
619 + skb_reserve(odev->skb_rx_buf,
620 + 2 + odev->net->hard_header_len);
621 +
622 + /* Copy what we got so far.
623 + make room for iphdr after tail. */
624 + tmp_rx_buf = skb_put(odev->skb_rx_buf, sizeof(struct iphdr));
625 + memcpy(tmp_rx_buf, (char *)&(odev->rx_ip_hdr),
626 + sizeof(struct iphdr));
627 +
628 + /* ETH_HLEN */
629 + odev->rx_buf_size = odev->net->hard_header_len + sizeof(struct iphdr);
630 +
631 + /* Filip actually use .tot_len */
632 + odev->rx_buf_missing = frame_len - sizeof(struct iphdr);
633 + odev->rx_parse_state = WAIT_DATA;
634 + }
635 + break;
636 +
637 + case WAIT_DATA:
638 + temp_bytes =
639 + (count <
640 + odev->rx_buf_missing) ? count : odev->rx_buf_missing;
641 +
642 + /* copy the rest of the bytes that are left in the buffer
643 + into the waiting sk_buf. Make room for temp_bytes after tail. */
644 + tmp_rx_buf = skb_put(odev->skb_rx_buf, temp_bytes);
645 + memcpy(tmp_rx_buf, ip_pkt + buffer_offset, temp_bytes);
646 +
647 + odev->rx_buf_missing -= temp_bytes;
648 + count -= temp_bytes;
649 + buffer_offset += temp_bytes;
650 + odev->rx_buf_size += temp_bytes;
651 + if (!odev->rx_buf_missing) {
652 + /* Packet is complete. Inject into stack. */
653 + {
654 + /* Add fake ethernet header. */
655 + eth_head = (struct ethhdr *)skb_push(odev->skb_rx_buf,
656 + odev->net->hard_header_len); /* decrease headroom */
657 + memcpy(eth_head, &odev->dummy_eth_head,
658 + sizeof(struct ethhdr));
659 +#if 0
660 + memcpy(eth_head->h_dest, odev->net->dev_addr , ETH_ALEN); /* driver MAC */
661 + memcpy(eth_head->h_source, dummy_mac, ETH_ALEN); /* from dummy device */
662 + eth_head->h_proto = htons(ETH_P_IP);
663 +#endif
664 +
665 + /* Not sure here either */
666 + odev->skb_rx_buf->protocol = eth_type_trans(odev->skb_rx_buf, odev->net);
667 + odev->skb_rx_buf->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
668 +
669 +#ifdef DEBUG
670 + DUMP(ip_pkt, min(128, count));
671 +#endif
672 +
673 + /* Ship it off to the kernel */
674 + netif_rx(odev->skb_rx_buf);
675 + odev->skb_rx_buf = NULL; /* No longer our buffer. */
676 +
677 + /* update out statistics */
678 + odev->stats.rx_packets++;
679 +
680 + /* Hmmm, wonder if we have received the IP len or the ETH len. */
681 + odev->stats.rx_bytes += odev->rx_buf_size;
682 + }
683 + odev->rx_buf_size = 0;
684 + odev->rx_buf_missing = sizeof(struct iphdr);
685 + odev->rx_parse_state = WAIT_IP;
686 + }
687 + break;
688 +
689 + case WAIT_SYNC:
690 + D(" W_S");
691 + count = 0;
692 + break;
693 + default:
694 + D(" ");
695 + count--;
696 + break;
697 + }
698 + }
699 +}
700 +
701 +/* Moving data from usb to kernel (in interrupt state) */
702 +
703 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
704 +static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
705 +#else
706 +static void read_bulk_callback(struct urb *urb)
707 +#endif
708 +{
709 + struct hso_priv *odev = urb->context;
710 + struct net_device *net;
711 + int res;
712 + unsigned long flags;
713 + int status = urb->status; /* preparation for removal of
714 + status from struct urb */
715 +
716 + if (status) {
717 + if(status != -ESHUTDOWN) {
718 + D1("nonzero bulk status received: %d", status);
719 + }
720 + return;
721 + }
722 +
723 + /* Sanity check */
724 + if (!odev || !test_bit(HSO_NET_RUNNING, &odev->flags)) {
725 + D1("BULK IN callback but driver is not active!");
726 + return;
727 + }
728 +
729 + net = odev->net;
730 + if (!netif_device_present(net)) {
731 + /* Somebody killed our network interface... */
732 + return;
733 + }
734 +
735 + if (urb->actual_length) {
736 + /* Handle the IP stream, add header and push it
737 + onto network stack if the packet is complete. */
738 + spin_lock_irqsave(&odev->net_lock,flags);
739 + packetizeRx(odev, urb->transfer_buffer, urb->actual_length);
740 + spin_unlock_irqrestore(&odev->net_lock,flags);
741 + }
742 +
743 + /* We are done with this URB, resubmit it.
744 + Prep the USB to wait for another frame. Reuse same as received.
745 + */
746 + usb_fill_bulk_urb(
747 + urb,
748 + odev->usb,
749 + usb_rcvbulkpipe(odev->usb, odev->mux_ep_bulk_in),
750 + urb->transfer_buffer,
751 + MUX_BULK_RX_BUF_SIZE,
752 + read_bulk_callback,
753 + odev);
754 +
755 + /* Give this to the USB subsystem so it can tell us
756 + when more data arrives.
757 + */
758 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
759 + if ((res = usb_submit_urb(urb, GFP_ATOMIC))) {
760 +#else
761 + if ((res = usb_submit_urb(urb))) {
762 +#endif
763 + WARN("%s failed submit mux_bulk_rx_urb %d", __FUNCTION__, res);
764 + }
765 +}
766 +
767 +/* This will tell kernel to send us packets again */
768 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
769 +static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
770 +#else
771 +static void write_bulk_callback(struct urb *urb)
772 +#endif
773 +{
774 + struct hso_priv *odev = urb->context;
775 + int status = urb->status;
776 +
777 + D1("-----------------------------------");
778 +
779 + /* Sanity check */
780 + if (!odev || !test_bit(HSO_NET_RUNNING, &odev->flags)) {
781 + ERR("write_bulk_callback: device not running");
782 + return;
783 + }
784 +
785 + /* Do we still have a valid kernel network device? */
786 + if (!netif_device_present(odev->net)) {
787 + ERR("write_bulk_callback: net device not present");
788 + return;
789 + }
790 +
791 + if (status) {
792 + D1("%s: TX status %d", odev->net->name, status);
793 + }
794 +
795 + /* Tell the network interface we are
796 + ready for another frame
797 + */
798 + netif_wake_queue(odev->net);
799 +}
800 +
801 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
802 +static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
803 +#else
804 +static void ctrl_callback(struct urb *urb)
805 +#endif
806 +{
807 + struct hso_serial *serial = urb->context;
808 + struct usb_ctrlrequest *req = NULL;
809 + int status = urb->status;
810 +
811 + if (!serial) {
812 + return;
813 + }
814 +
815 + req = (struct usb_ctrlrequest *)(urb->setup_packet);
816 +
817 + D4("\n-------------------- got ctrl callback %02x ---------------------", status);
818 +#if 0
819 + /* This is old values */
820 + if (req) {
821 + D4("bRequestType: 0x%02x", req->bRequestType);
822 + D4("bRequest: 0x%02x", req->bRequest);
823 + D4("wValue: 0x%04x", req->wValue);
824 + D4("wIndex: 0x%04x", req->wIndex);
825 + D4("wLength: 0x%04x (%d)", req->wLength, req->wLength);
826 + }
827 +#endif
828 +
829 + if (status) {
830 + if(status != -ESHUTDOWN) {
831 + D1("nonzero ctrl status received: %d", status);
832 + }
833 + return;
834 + }
835 +
836 + D4("actual length = %d\n", urb->actual_length);
837 +
838 +#ifdef DEBUG
839 + DUMP1(urb->transfer_buffer, urb->actual_length);
840 +#endif
841 +
842 + if (req->bRequestType ==
843 + (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) {
844 + if (serial->open_count > 0)
845 + put_rxbuf_data(urb, serial);
846 +
847 + D1("urb->actual_length == %d", urb->actual_length);
848 +
849 + /* Re issue a read as long as we receive data. */
850 + if (urb->actual_length != 0) {
851 + hso_mux_serial_read(serial->odev, serial);
852 + } else {
853 + clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags);
854 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
855 + hso_mux_submit_intr_urb(serial->odev,GFP_ATOMIC); // 2.6 needs provides one shot interrupt
856 +#endif
857 + }
858 +
859 + } else { /* write request. */
860 + if (urb->actual_length != 0) {
861 + clear_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags);
862 + }
863 + }
864 +}
865 +
866 +/* Diag/CS port only
867 + Interrupt state
868 + */
869 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
870 +static void hso_std_serial_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
871 +#else
872 +static void hso_std_serial_read_bulk_callback(struct urb *urb)
873 +#endif
874 +{
875 + struct hso_serial *serial = urb->context;
876 + int res;
877 + int status = urb->status;
878 +/* struct usb_ctrlrequest *req = NULL; */
879 +
880 + if (!serial) {
881 + return;
882 + }
883 +
884 + D4("\n-------------------- got serial_read_bulk callback %02x ---------------------", status);
885 +
886 + if (status) {
887 + if(status != -ESHUTDOWN) {
888 + D1("nonzero read bulk status received: %d", status);
889 + }
890 + return;
891 + }
892 +
893 + D1("actual length = %d\n", urb->actual_length);
894 +#ifdef DEBUG
895 + DUMP1(urb->transfer_buffer, urb->actual_length);
896 +#endif
897 +
898 + if (serial->open_count == 0) /* No one is listening, dont resubmit it.. */
899 + return;
900 +
901 + if (status == 0) { /* Valid data */
902 + put_rxbuf_data(urb, serial);
903 + } else if (status == -ENOENT || status == -ECONNRESET) {
904 + /* Unlinked - check for throttled port. */
905 + D2(" port %d, successfully unlinked urb", serial->minor);
906 + } else {
907 + D2(" port %d, status = %d for read urb", serial->minor, status);
908 + return;
909 + }
910 +
911 + /* We are done with this URB, resubmit it.
912 + Prep the USB to wait for another frame */
913 + usb_fill_bulk_urb(serial->rx_urb,
914 + serial->odev->usb,
915 + usb_rcvbulkpipe(serial->odev->usb,
916 + serial->ep_bulk_in),
917 + serial->rx_data,
918 + serial->rx_data_length,
919 + hso_std_serial_read_bulk_callback,
920 + serial);
921 +
922 + /* Give this to the USB subsystem so it can tell us
923 + when more data arrives.
924 + */
925 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
926 + if ((res = usb_submit_urb(serial->rx_urb, GFP_ATOMIC))) {
927 +#else
928 + if ((res = usb_submit_urb(serial->rx_urb))) {
929 +#endif
930 + ERR("%s failed submit serial rx_urb %d", __FUNCTION__, res);
931 + }
932 +}
933 +
934 +/* Diag/CS port only
935 + */
936 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
937 +static void hso_std_serial_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
938 +#else
939 +static void hso_std_serial_write_bulk_callback(struct urb *urb)
940 +#endif
941 +{
942 + struct hso_serial *serial = urb->context;
943 + int status = urb->status;
944 +
945 + if (!serial)
946 + return;
947 +
948 + D1(" ");
949 +
950 + clear_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags);
951 +
952 + if (status) {
953 + if(status != -ESHUTDOWN) {
954 + D1("nonzero write bulk status received: %d", status);
955 + }
956 + return;
957 + }
958 +
959 + return;
960 +}
961 +
962 +static int mux_device_request(struct hso_serial *serial, u8 type, u16 port,
963 + struct urb *ctrl_urb,
964 + struct usb_ctrlrequest *ctrl_req, u8 *ctrl_urb_data,
965 + u32 size)
966 +{
967 + int res = 0;
968 + int pipe = -1;
969 +
970 + /* Sanity check */
971 + if (!serial || !ctrl_urb || !ctrl_req) {
972 + ERR("Wrong arguments ");
973 + return -EINVAL;
974 + }
975 +
976 + ctrl_req->wValue = 0;
977 + ctrl_req->wIndex = port; /* port to send to */
978 + ctrl_req->wLength = size; /* Is this supposed to be this??? */
979 +
980 + if (type == GET_ENCAPSULATED_RESPONSE) { /* Reading command */
981 + ctrl_req->bRequestType =
982 + USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE;
983 + ctrl_req->bRequest = GET_ENCAPSULATED_RESPONSE;
984 + pipe = usb_rcvctrlpipe(serial->odev->usb, 0);
985 + } else { /* Writing command */
986 + ctrl_req->bRequestType =
987 + USB_DIR_OUT | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE;
988 + ctrl_req->bRequest = SEND_ENCAPSULATED_COMMAND;
989 + pipe = usb_sndctrlpipe(serial->odev->usb, 0);
990 +
991 +#ifdef DEBUG
992 + DUMP(ctrl_urb_data, size);
993 +#endif
994 + }
995 +
996 + D2("%s command (%02x) len: %d, port: %d",
997 + type == GET_ENCAPSULATED_RESPONSE ? "Read" : "Write",
998 + ctrl_req->bRequestType, ctrl_req->wLength, port);
999 +
1000 + /* Load ctrl urb */
1001 + ctrl_urb->transfer_flags = 0;
1002 +
1003 + usb_fill_control_urb(ctrl_urb,
1004 + serial->odev->usb,
1005 + pipe,
1006 + (u8 *) ctrl_req,
1007 + ctrl_urb_data,
1008 + size,
1009 + ctrl_callback,
1010 + serial);
1011 +
1012 + /* Send it on merry way */
1013 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1014 + if ((res = usb_submit_urb(ctrl_urb, GFP_ATOMIC))) {
1015 +#else
1016 + if ((res = usb_submit_urb(ctrl_urb))) {
1017 +#endif
1018 + ERR("%s failed submit ctrl_urb %d type %d", __FUNCTION__, res, type);
1019 + return res;
1020 + }
1021 +
1022 + return size;
1023 +}
1024 +
1025 +static int hso_mux_serial_read(struct hso_priv *odev, struct hso_serial *serial)
1026 +{
1027 + int rc = 0;
1028 +
1029 + memset(serial->rx_data, 0, CTRL_URB_RX_SIZE); /* rx_data_length */
1030 +
1031 + rc = mux_device_request(serial,
1032 + GET_ENCAPSULATED_RESPONSE,
1033 + serial->mux,
1034 + serial->rx_urb,
1035 + &serial->ctrl_req_rx,
1036 + serial->rx_data, serial->rx_data_length);
1037 + return rc;
1038 +}
1039 +
1040 +/*
1041 + We we have a pending response, here we know what port to send the reponse to
1042 + */
1043 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
1044 +static void intr_callback(struct urb *urb, struct pt_regs *regs)
1045 +#else
1046 +static void intr_callback(struct urb *urb)
1047 +#endif
1048 +{
1049 + struct hso_priv *odev = urb->context;
1050 + struct hso_serial *serial;
1051 + unsigned char *port_req;
1052 + int status = urb->status;
1053 + int i;
1054 +
1055 + if (!odev) {
1056 + return;
1057 + }
1058 +
1059 + D4("\n---------------------- got intr callback %02x ---------------------", status);
1060 +
1061 + if (status) {
1062 + if(status != -ESHUTDOWN) {
1063 + D1("%s intr status %d", odev->net->name, status);
1064 + }
1065 + return;
1066 + }
1067 +
1068 + port_req = urb->transfer_buffer;
1069 +
1070 + D4(" port_req = 0x%.2X\n", *port_req);
1071 +
1072 + for (i = 0; i < 8; i++) { /* max 8 channels on MUX */
1073 + serial = get_serial_by_odev_and_mux(odev,i);
1074 + if ((*port_req & (1 << i)) && serial != NULL) {
1075 + D1("Pending read interrupt on port %d\n", i);
1076 + if (!test_and_set_bit(HSO_SERIAL_FLAG_RX_SENT,
1077 + &serial->flags)) {
1078 + /* Setup and send a ctrl req read on port i */
1079 + hso_mux_serial_read(odev,serial);
1080 + } else {
1081 + D1("Already pending a read on port %d\n", i);
1082 + }
1083 + }
1084 + }
1085 +
1086 + /* D1("issue ctrl read "); */
1087 + /* debug_read(odev, serial_table[0]); */
1088 +}
1089 +
1090 +static inline int enable_net_traffic(struct hso_priv *odev)
1091 +{
1092 + D1("Does not do anything yet.");
1093 + return 0;
1094 +}
1095 +
1096 +static inline void disable_net_traffic(struct hso_priv *odev)
1097 +{
1098 + D1("Does not do anything yet");
1099 +}
1100 +
1101 +/*
1102 + Callback routines for kernel Ethernet Device
1103 + */
1104 +
1105 +static void hso_net_tx_timeout(struct net_device *net)
1106 +{
1107 + struct hso_priv *odev = netdev_priv(net);
1108 +
1109 + D1("-----------------------------------");
1110 +
1111 + if (!odev) {
1112 + return;
1113 + }
1114 +
1115 + /* Tell syslog we are hosed. */
1116 + WARN("%s: Tx timed out.", net->name);
1117 +
1118 + /* Tear the waiting frame off the list */
1119 + usb_unlink_urb(odev->mux_bulk_tx_urb);
1120 +
1121 + /* Update statistics */
1122 + odev->stats.tx_errors++;
1123 +}
1124 +
1125 +/* Moving data from kernel to usb
1126 + */
1127 +static int hso_net_start_xmit(struct sk_buff *skb, struct net_device *net)
1128 +{
1129 + struct hso_priv *odev = netdev_priv(net);
1130 + int res;
1131 +
1132 + /* Tell the kernel, "No more frames 'til we are done
1133 + with this one.'
1134 + */
1135 + netif_stop_queue(net);
1136 +
1137 + skb_pull(skb, ETH_HLEN);
1138 +
1139 +#ifdef DEBUG
1140 + DUMP1(skb->data, skb->len);
1141 +#endif
1142 +
1143 + /* Copy it from kernel memory to OUR memory */
1144 + memcpy(odev->mux_bulk_tx_buf, skb->data, skb->len);
1145 +
1146 + /* Fill in the URB for shipping it out. */
1147 + usb_fill_bulk_urb(odev->mux_bulk_tx_urb, odev->usb,
1148 + usb_sndbulkpipe(odev->usb, odev->mux_ep_bulk_out),
1149 + odev->mux_bulk_tx_buf,
1150 + skb->len,
1151 + write_bulk_callback, odev);
1152 +
1153 + D1("len: %d/%d", skb->len, MUX_BULK_TX_BUF_SIZE);
1154 +
1155 + /* Deal with the Zero Length packet problem, I hope */
1156 + odev->mux_bulk_tx_urb->transfer_flags |= URB_ZERO_PACKET;
1157 +
1158 + /* Send the URB on its merry way. */
1159 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1160 + if ((res = usb_submit_urb(odev->mux_bulk_tx_urb, GFP_ATOMIC))) {
1161 +#else
1162 + if ((res = usb_submit_urb(odev->mux_bulk_tx_urb))) {
1163 +#endif
1164 + WARN("failed mux_bulk_tx_urb %d", res);
1165 + odev->stats.tx_errors++;
1166 + netif_start_queue(net);
1167 + } else {
1168 + odev->stats.tx_packets++;
1169 + odev->stats.tx_bytes += skb->len;
1170 + net->trans_start = jiffies; /* And tell the kernel when
1171 + the last transmit started. */
1172 + }
1173 +
1174 + dev_kfree_skb(skb);
1175 +
1176 + return res;
1177 +}
1178 +
1179 +static struct net_device_stats *hso_net_get_stats(struct net_device *net)
1180 +{
1181 + return &((struct hso_priv *) netdev_priv(net))->stats;
1182 +}
1183 +
1184 +/* AJB, called when net I/F is brought up by ifconfig */
1185 +static int hso_net_open(struct net_device *net)
1186 +{
1187 + struct hso_priv *odev = netdev_priv(net);
1188 + int res;
1189 + int i;
1190 + unsigned long flags;
1191 +
1192 + /* Turn on the USB and let the packets flow!!! */
1193 + if ((res = enable_net_traffic(odev))) {
1194 + ERR("%s can't enable_net_traffic() - %d", __FUNCTION__, res);
1195 + return -EIO;
1196 + }
1197 + /* STTH test code. reset counter. */
1198 + odev->stats.rx_packets = 0;
1199 +
1200 + spin_lock_irqsave(&odev->net_lock,flags);
1201 + odev->rx_parse_state = WAIT_IP;
1202 + odev->rx_buf_size = 0;
1203 + odev->rx_buf_missing = sizeof(struct iphdr);
1204 + spin_unlock_irqrestore(&odev->net_lock,flags);
1205 +
1206 + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
1207 + /* Prep a receive URB */
1208 + usb_fill_bulk_urb(odev->mux_bulk_rx_urb_pool[i],
1209 + odev->usb,
1210 + usb_rcvbulkpipe(odev->usb,
1211 + odev->mux_ep_bulk_in),
1212 + odev->mux_bulk_rx_buf_pool[i],
1213 + MUX_BULK_RX_BUF_SIZE,
1214 + read_bulk_callback, odev);
1215 +
1216 + /* Put it out there so the device can send us stuff */
1217 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1218 + if ((res = usb_submit_urb(odev->mux_bulk_rx_urb_pool[i], GFP_KERNEL))) {
1219 +#else
1220 + if ((res = usb_submit_urb(odev->mux_bulk_rx_urb_pool[i]))) {
1221 +#endif
1222 + WARN("%s failed mux_bulk_rx_urb %d", __FUNCTION__, res);
1223 + }
1224 + }
1225 + /* Tell the kernel we are ready to start receiving from it */
1226 + netif_start_queue(net);
1227 +
1228 + /* We are up and running. */
1229 + set_bit(HSO_NET_RUNNING, &odev->flags);
1230 +
1231 + return 0;
1232 +}
1233 +
1234 +/* AJB, called when net I/F is brought down by ifconfig */
1235 +static int hso_net_close(struct net_device *net)
1236 +{
1237 + struct hso_priv *odev = netdev_priv(net);
1238 + int i;
1239 +
1240 + clear_bit(HSO_NET_RUNNING, &odev->flags);
1241 +
1242 + netif_stop_queue(net);
1243 +
1244 + /* If we are not already unplugged, turn off USB traffic */
1245 + if (!test_bit(HSO_CARD_UNPLUG, &odev->flags)) {
1246 + disable_net_traffic(odev);
1247 + }
1248 +
1249 + /* We don't need the URBs anymore. */
1250 + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
1251 + usb_unlink_urb(odev->mux_bulk_rx_urb_pool[i]);
1252 + }
1253 + usb_unlink_urb(odev->mux_bulk_tx_urb);
1254 +
1255 + /* interrupt urb is still needed for the serial to work.... */
1256 +
1257 + return 0;
1258 +}
1259 +
1260 +static int netdev_ethtool_ioctl(struct net_device *net, struct ifreq *rq)
1261 +{
1262 + struct hso_priv *odev = netdev_priv(net);
1263 + u32 cmd;
1264 + char tmp[40];
1265 +
1266 + if (copy_from_user(&cmd, rq->ifr_data,sizeof(cmd)))
1267 + return -EFAULT;
1268 +
1269 + switch (cmd) {
1270 + /* get driver info */
1271 + case ETHTOOL_GDRVINFO: {
1272 + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
1273 + strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN);
1274 + strncpy(info.version, DRIVER_VERSION,
1275 + ETHTOOL_BUSINFO_LEN);
1276 + sprintf(tmp, "usb%d:%d", odev->usb->bus->busnum,
1277 + odev->usb->devnum);
1278 + strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
1279 + sprintf(tmp, "%s %x.%x", driver_name,
1280 + ((odev->bcdCDC & 0xff00) >> 8),
1281 + (odev->bcdCDC & 0x00ff));
1282 + strncpy(info.fw_version, tmp, ETHTOOL_BUSINFO_LEN);
1283 +
1284 + if (copy_to_user(rq->ifr_data, &info, sizeof(info)))
1285 + return -EFAULT;
1286 +
1287 + return 0;
1288 + }
1289 + /* get link status */
1290 + case ETHTOOL_GLINK: {
1291 + struct ethtool_value edata = { ETHTOOL_GLINK };
1292 + edata.data = netif_carrier_ok(net);
1293 +
1294 + if (copy_to_user(rq->ifr_data, &edata, sizeof(edata)))
1295 + return -EFAULT;
1296 +
1297 + return 0;
1298 + }
1299 + }
1300 + D1("Got unsupported ioctl: %x", cmd);
1301 + return -EOPNOTSUPP; /* the ethtool user space tool relies on this */
1302 +}
1303 +
1304 +static int hso_net_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
1305 +{
1306 + struct hso_priv *odev = netdev_priv(net);
1307 +
1308 + switch (cmd) {
1309 +
1310 + case SIOCDEVPRIVATE + 1:/* Chose this one because SIOCDEVPRIVATE used somewhere else in this code */
1311 + D5("Transmitted: %lu", odev->stats.tx_bytes);
1312 + rq->ifr_ifru.ifru_ivalue = odev->stats.tx_bytes;
1313 + return 0;
1314 +
1315 + case SIOCETHTOOL:
1316 + return netdev_ethtool_ioctl(net, rq);
1317 +
1318 + default:
1319 + return -ENOTTY; /* per ioctl man page */
1320 + }
1321 +}
1322 +
1323 +/* FIXME AJB, work out what we need to do with multicast */
1324 +static void hso_net_set_multicast(struct net_device *net)
1325 +{
1326 + struct hso_priv *odev = netdev_priv(net);
1327 + int i;
1328 + __u8 *buf;
1329 +
1330 + /* Tell the kernel to stop sending us frames while we get this all set up. */
1331 + netif_stop_queue(net);
1332 +
1333 + /* Note: do not reorder, GCC is clever about common statements. */
1334 + if (net->flags & IFF_PROMISC) {
1335 + /* Unconditionally log net taps. */
1336 + D1("%s: Promiscuous mode enabled", net->name);
1337 + odev->mode_flags =
1338 + MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED |
1339 + MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST |
1340 + MODE_FLAG_PROMISCUOUS;
1341 + } else if (net->mc_count > odev->wNumberMCFilters) {
1342 + /* Too many to filter perfectly -- accept all multicasts. */
1343 + D1("%s: too many MC filters for hardware, using allmulti",
1344 + net->name);
1345 + odev->mode_flags =
1346 + MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED |
1347 + MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST;
1348 + } else if (net->flags & IFF_ALLMULTI) {
1349 + /* Filter in software */
1350 + D1("%s: using allmulti", net->name);
1351 + odev->mode_flags =
1352 + MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED |
1353 + MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST;
1354 + } else {
1355 + /* do multicast filtering in hardware */
1356 + struct dev_mc_list *mclist;
1357 + D1("%s: set multicast filters", net->name);
1358 + odev->mode_flags =
1359 + MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED |
1360 + MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST;
1361 + if (!(buf = kmalloc(6 * net->mc_count, GFP_ATOMIC))) {
1362 + ERR("No memory to allocate?");
1363 + goto exit;
1364 + }
1365 + for (i = 0, mclist = net->mc_list;
1366 + mclist && i < net->mc_count; i++, mclist = mclist->next) {
1367 + memcpy(&mclist->dmi_addr, &buf[i * 6], 6);
1368 + }
1369 +#if 0
1370 + usb_control_msg(odev->usb, usb_sndctrlpipe(odev->usb, 0), SET_ETHERNET_MULTICAST_FILTER, /* request */
1371 + USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
1372 + cpu_to_le16(net->mc_count), /* value */
1373 + cpu_to_le16((u16) odev->mux_interface), /* index */
1374 + buf, (6 * net->mc_count), /* size */
1375 + HZ); /* timeout */
1376 +#endif
1377 + kfree(buf);
1378 + }
1379 +
1380 + exit:
1381 + /* Tell the kernel to start giving frames to us again. */
1382 + netif_wake_queue(net);
1383 +}
1384 +
1385 +static int parse_option_information(unsigned char *data, int length,
1386 + struct hso_priv *odev)
1387 +{
1388 + int i = 0;
1389 +
1390 + if (length != 3) {
1391 + ERR("Extralen don't contain expected data! length:%d", length);
1392 + return -1;
1393 + }
1394 +
1395 + /* Length */
1396 + odev->option_info.length = data[i++];
1397 +
1398 + /* Type */
1399 + odev->option_info.descriptor_type = data[i++];
1400 +
1401 + if (odev->option_info.descriptor_type != CS_INTERFACE_VAL) {
1402 + ERR("Expected CS_INTERFACE_VAL, got: %02x",
1403 + odev->option_info.descriptor_type);
1404 + return -1;
1405 + }
1406 +
1407 + /* Enabled modem ports */
1408 + odev->option_info.enabled_ports = data[i++];
1409 +
1410 + D1("length: %02x, type: %02x, subtype: %02x",
1411 + odev->option_info.length,
1412 + odev->option_info.descriptor_type,
1413 + odev->option_info.enabled_ports);
1414 +
1415 + return 0;
1416 +}
1417 +
1418 +static int get_mux_endpoints(struct usb_interface *intf, struct hso_priv *odev)
1419 +{
1420 + int i;
1421 + struct usb_endpoint_descriptor *endp = NULL;
1422 +
1423 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1424 + struct usb_host_interface *iface_desc = intf->cur_altsetting;
1425 + struct usb_interface_descriptor *desc = &(intf->cur_altsetting->desc);
1426 +#else
1427 + struct usb_interface_descriptor *desc = &(intf->altsetting[intf->act_altsetting]);
1428 +#endif
1429 +
1430 + /* Start out assuming we won't find anything we can use */
1431 + odev->mux_ep_bulk_out = odev->mux_ep_bulk_in = odev->mux_ep_intr = 0;
1432 +
1433 + for (i = 0; i < desc->bNumEndpoints; i++) {
1434 +
1435 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1436 + endp = &(iface_desc->endpoint[i].desc);
1437 +#else
1438 + endp = &(desc->endpoint[i]);
1439 +#endif
1440 + if (!usb_endpoint_xfer_bulk(endp)) {
1441 +
1442 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1443 + if (!iface_desc->endpoint[i].extralen ||
1444 + parse_option_information( iface_desc->endpoint[i].extra,
1445 + iface_desc->endpoint[i].extralen,
1446 + odev)) {
1447 +#else
1448 + if (!endp->extralen ||
1449 + parse_option_information( endp->extra,
1450 + endp->extralen,
1451 + odev)) {
1452 +#endif
1453 + ERR("Could not get option specific data, not our device then");
1454 + return -1;
1455 + }
1456 +
1457 + odev->mux_ep_intr =
1458 + endp->bEndpointAddress & 0x7F;
1459 + odev->mux_bInterval = endp->bInterval;
1460 + odev->mux_ep_intr_size = endp->wMaxPacketSize;
1461 + } else {
1462 + if (usb_endpoint_is_bulk_in(endp)) {
1463 + odev->mux_ep_bulk_in =
1464 + endp->bEndpointAddress & 0x7F;
1465 + odev->mux_ep_bulk_in_size =
1466 + endp->wMaxPacketSize;
1467 + } else {
1468 + odev->mux_ep_bulk_out = endp->bEndpointAddress;
1469 + odev->mux_ep_bulk_out_size =
1470 + endp->wMaxPacketSize;
1471 + }
1472 + }
1473 + }
1474 +
1475 + /* Now make sure we got both an IN and an OUT */
1476 + if (odev->mux_ep_bulk_in && odev->mux_ep_bulk_out && odev->mux_ep_intr) {
1477 + D1("detected BULK IN/OUT/interrupt packets of [size: %d/%d/%d, addr: %02x/%02x/%02x]",
1478 + odev->mux_ep_bulk_in_size,
1479 + odev->mux_ep_bulk_out_size,
1480 + odev->mux_ep_intr_size,
1481 + odev->mux_ep_bulk_in,
1482 + odev->mux_ep_bulk_out,
1483 + odev->mux_ep_intr);
1484 + return 0;
1485 + }
1486 + return -1;
1487 +}
1488 +
1489 +static int get_std_serial_endpoints(struct usb_interface *intf, struct hso_serial *serial)
1490 +{
1491 + int i;
1492 + struct usb_endpoint_descriptor *endp = NULL;
1493 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1494 + struct usb_host_interface *iface_desc = intf->cur_altsetting;
1495 + struct usb_interface_descriptor *desc = &(intf->cur_altsetting->desc);
1496 +#else
1497 + struct usb_interface_descriptor *desc = &(intf->altsetting[intf->act_altsetting]);
1498 +#endif
1499 +
1500 + /* Start out assuming we won't find anything we can use */
1501 + serial->ep_bulk_out = serial->ep_bulk_in = 0;
1502 +
1503 + for (i = 0; i < desc->bNumEndpoints; i++) {
1504 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1505 + endp = &(iface_desc->endpoint[i].desc);
1506 +#else
1507 + endp = &(desc->endpoint[i]);
1508 +#endif
1509 + if (!usb_endpoint_xfer_bulk(endp)) {
1510 + continue;
1511 + }
1512 +
1513 + /* Check the first endpoint to see if it is IN or OUT */
1514 + if (usb_endpoint_is_bulk_in(endp)) {
1515 + serial->ep_bulk_in = endp->bEndpointAddress & 0x7F;
1516 + serial->ep_bulk_in_size = endp->wMaxPacketSize;
1517 + } else {
1518 + serial->ep_bulk_out = endp->bEndpointAddress;
1519 + serial->ep_bulk_out_size = endp->wMaxPacketSize;
1520 + }
1521 + }
1522 +
1523 + /* FIXME AJB, need to handle the interrupt endpoint also
1524 + for Circuit Switched port */
1525 +
1526 + /* Now make sure we got both an IN and an OUT */
1527 + if (serial->ep_bulk_in && serial->ep_bulk_out) {
1528 + D1("detected BULK IN/OUT packets of [size: %d/%d, addr: %02x/%02x]",
1529 + serial->ep_bulk_in_size,
1530 + serial->ep_bulk_out_size,
1531 + serial->ep_bulk_in,
1532 + serial->ep_bulk_out);
1533 + return 0;
1534 + }
1535 + return -1;
1536 +}
1537 +
1538 +
1539 +#define UMS_SWITCH_CMD_LEN 31
1540 +
1541 +
1542 +static int check_ums_and_send_rezero(struct usb_interface *intf, struct usb_device *usb)
1543 +{
1544 + struct usb_endpoint_descriptor *endp = NULL;
1545 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1546 + struct usb_host_interface *iface_desc = intf->cur_altsetting;
1547 + struct usb_interface_descriptor *desc = &(intf->cur_altsetting->desc);
1548 +#else
1549 + struct usb_interface_descriptor *desc = &(intf->altsetting[intf->act_altsetting]);
1550 +#endif
1551 + int retval = 0;
1552 + int actual_length;
1553 +
1554 + u8 UmsSwitchCmd[] =
1555 + {
1556 + 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12,
1557 + 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x01,
1558 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1559 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1560 + };
1561 +
1562 + /* Check UMS interface */
1563 + if (desc->bNumEndpoints == 2 &&
1564 + desc->bInterfaceClass == 0x08 &&
1565 + desc->bInterfaceSubClass == 0x06 &&
1566 + desc->bInterfaceProtocol == 0x50) {
1567 + D1("UMS interface found");
1568 +
1569 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1570 + if (usb_endpoint_is_bulk_out(&iface_desc->endpoint[0].desc)) {
1571 + endp = &iface_desc->endpoint[0].desc;
1572 + } else {
1573 + endp = &iface_desc->endpoint[1].desc;
1574 + }
1575 +#else
1576 + if (usb_endpoint_is_bulk_out(&desc->endpoint[0])) {
1577 + endp = &desc->endpoint[0];
1578 + } else {
1579 + endp = &desc->endpoint[1];
1580 + }
1581 +#endif
1582 +
1583 + if ( 0 != usb_bulk_msg (usb,
1584 + usb_sndbulkpipe(usb, endp->bEndpointAddress),
1585 + (void*)UmsSwitchCmd,
1586 + UMS_SWITCH_CMD_LEN,
1587 + &actual_length,
1588 + 0)) {
1589 + WARN("send UMS switch failed");
1590 + } else {
1591 + D1("UMS switch done");
1592 + retval = 1;
1593 + }
1594 + }
1595 +
1596 + return retval;
1597 +}
1598 +
1599 +
1600 +static int check_and_claim_interfaces(struct usb_device *usb,
1601 + struct hso_priv *odev)
1602 +{
1603 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1604 + struct usb_config_descriptor *desc = &(usb->actconfig->desc);
1605 +#else
1606 + struct usb_config_descriptor *desc = usb->actconfig;
1607 +#endif
1608 + int i;
1609 + int result = 0;
1610 +
1611 + /*
1612 + 0. Multiplexed interface - hsdpa net + muxed serial ports.
1613 + 1. QXDM port - only used for debug
1614 + 2. Modem port - only used for Circuit switched connections.
1615 + */
1616 +
1617 + /* AJB, only check 1 and 2, since 0 is claimed for us prior to probe */
1618 + for (i = 1; i < desc->bNumInterfaces; i++) {
1619 + if (usb_interface_claimed(usb_ifnum_to_if(usb,i))) {
1620 + D1("Interface %d already claimed", i);
1621 + result = -1;
1622 + }
1623 + }
1624 + if (result)
1625 + return result;
1626 +
1627 + D1("No one has claimed our auxiliary interfaces, good");
1628 +
1629 + /* Check if we found an Option device */
1630 + if (get_mux_endpoints(usb_ifnum_to_if(usb,0), odev)) {
1631 + D1("Mux interface endpoints did not suit us");
1632 + goto exit;
1633 + }
1634 +
1635 + /* MUX interface is claimed for us already */
1636 +
1637 + /* Claim QXDM interface */
1638 + usb_driver_claim_interface(&hso_driver,usb_ifnum_to_if(usb,1),odev);
1639 +
1640 + /* Claim C/S interface */
1641 + if(desc->bNumInterfaces > 2) {
1642 + usb_driver_claim_interface(&hso_driver,usb_ifnum_to_if(usb,2),odev);
1643 + }
1644 +
1645 + return desc->bNumInterfaces;
1646 +
1647 +exit:
1648 + return -EIO;
1649 +}
1650 +
1651 +static inline unsigned char hex2dec(unsigned char digit)
1652 +{
1653 +
1654 + if ((digit >= '0') && (digit <= '9')) {
1655 + return (digit - '0');
1656 + }
1657 + /* Map all characters to 0-15 */
1658 + if ((digit >= 'a') && (digit <= 'z')) {
1659 + return (digit - 'a' + 10) % 16;
1660 + }
1661 + if ((digit >= 'A') && (digit <= 'Z')) {
1662 + return (digit - 'A' + 10) % 16;
1663 + }
1664 +
1665 + return 16;
1666 +}
1667 +
1668 +/*
1669 + Use the serial number to generate the MAC address
1670 + FIXME AJB, unfortunately the devices I have, have this set to 'Serial Number'
1671 + and so generate the same MAC address :-(
1672 + */
1673 +static void set_ethernet_addr(struct hso_priv *odev)
1674 +{
1675 + unsigned char mac_addr[6];
1676 + int i;
1677 + int len;
1678 + unsigned char buffer[13];
1679 +
1680 + /* Let's assume we don't get anything */
1681 + mac_addr[0] = 0x00;
1682 + mac_addr[1] = 0x00;
1683 + mac_addr[2] = 0x00;
1684 + mac_addr[3] = 0x00;
1685 + mac_addr[4] = 0x00;
1686 + mac_addr[5] = 0x00;
1687 +
1688 + if (0 > (len = usb_string(odev->usb,
1689 + odev->usb->descriptor.iSerialNumber, buffer, 13))) {
1690 + ERR("Attempting to get MAC address failed: %d", -1 * len);
1691 + return;
1692 + }
1693 +
1694 + /* Sanity check */
1695 + if (len != 12) {
1696 + /* You gotta love failing sanity checks */
1697 + ERR("Attempting to get MAC address returned %d bytes", len);
1698 + return;
1699 + }
1700 +
1701 + /* Fill in the mac_addr */
1702 + for (i = 0; i < 6; i++) {
1703 + if ((16 == buffer[2 * i]) || (16 == buffer[2 * i + 1])) {
1704 + ERR("Bad value in MAC address i:%d", i);
1705 + } else {
1706 + mac_addr[i] =
1707 + (hex2dec(buffer[2 * i]) << 4) +
1708 + hex2dec(buffer[2 * i + 1]);
1709 + }
1710 + }
1711 +
1712 + mac_addr[0] = 0x00;
1713 + mac_addr[1] = 0x03;
1714 +
1715 + /* Now copy it over to our network device structure */
1716 + memcpy(odev->net->dev_addr, mac_addr, sizeof(mac_addr));
1717 +
1718 + /* Create the default fake ethernet header. */
1719 + memcpy(odev->dummy_eth_head.h_dest, mac_addr, ETH_ALEN);
1720 + memcpy(odev->dummy_eth_head.h_source, dummy_mac, ETH_ALEN);
1721 + odev->dummy_eth_head.h_proto = htons(ETH_P_IP);
1722 +}
1723 +
1724 +static void get_string(u8 * buf, int buf_len, int string_num, struct hso_priv *odev)
1725 +{
1726 + int len;
1727 +
1728 + if (!buf) {
1729 + ERR("No buffer?");
1730 + return;
1731 + }
1732 +
1733 + buf[0] = 0x00;
1734 +
1735 + if (string_num) {
1736 + /* Put it into its buffer */
1737 + len = usb_string(odev->usb, string_num, buf, buf_len);
1738 + /* Just to be safe */
1739 + buf[len] = 0x00;
1740 + }
1741 +}
1742 +
1743 +static void log_device_info(struct hso_priv *odev)
1744 +{
1745 + unsigned char manu[256];
1746 + unsigned char prod[256];
1747 + unsigned char sern[256];
1748 + unsigned char *mac_addr = odev->net->dev_addr;
1749 +
1750 + /* Try to get the device Manufacturer */
1751 + get_string(manu, sizeof(manu), odev->usb->descriptor.iManufacturer, odev);
1752 +
1753 + /* Try to get the device Product Name */
1754 + get_string(prod, sizeof(prod), odev->usb->descriptor.iProduct, odev);
1755 +
1756 + /* Try to get the device Serial Number */
1757 + get_string(sern, sizeof(sern), odev->usb->descriptor.iSerialNumber, odev);
1758 +
1759 + /* Now send everything we found to the syslog */
1760 + QFO("%s: %s %s %s", odev->net->name, manu, prod, sern);
1761 + QFO("%s: %02X:%02X:%02X:%02X:%02X:%02X",
1762 + odev->net->name,
1763 + mac_addr[0], mac_addr[1], mac_addr[2],
1764 + mac_addr[3], mac_addr[4], mac_addr[5]);
1765 +}
1766 +
1767 +static void hso_free_memory(struct hso_priv *odev)
1768 +{
1769 + int i;
1770 +
1771 + if (!odev)
1772 + return;
1773 +
1774 + if (odev->mux_intr_urb) {
1775 + usb_free_urb(odev->mux_intr_urb);
1776 + }
1777 + if (odev->mux_intr_buf) {
1778 + kfree(odev->mux_intr_buf);
1779 + }
1780 +
1781 + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
1782 + if (odev->mux_bulk_rx_urb_pool[i]) {
1783 + usb_free_urb(odev->mux_bulk_rx_urb_pool[i]);
1784 + }
1785 + if (odev->mux_bulk_rx_buf_pool[i]) {
1786 + kfree(odev->mux_bulk_rx_buf_pool[i]);
1787 + }
1788 + }
1789 + if (odev->mux_bulk_tx_urb) {
1790 + usb_free_urb(odev->mux_bulk_tx_urb);
1791 + }
1792 + if (odev->mux_bulk_tx_buf) {
1793 + kfree(odev->mux_bulk_tx_buf);
1794 + }
1795 +}
1796 +
1797 +static int hso_alloc_memory(struct hso_priv *odev) /* FIXME AJB, need to make cleanup error path */
1798 +{
1799 + int i;
1800 +
1801 + if (!odev)
1802 + return -1;
1803 +
1804 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1805 + if (!(odev->mux_intr_urb = usb_alloc_urb(0, GFP_KERNEL))) {
1806 +#else
1807 + if (!(odev->mux_intr_urb = usb_alloc_urb(0))) {
1808 +#endif
1809 + ERR("Could not allocate urb?");
1810 + return -1;
1811 + }
1812 + if (!(odev->mux_intr_buf = kzalloc(MUX_INTR_BUF_SIZE, GFP_KERNEL))) {
1813 + ERR("Could not allocate buf?");
1814 + return -1;
1815 + }
1816 +
1817 + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
1818 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1819 + if (!(odev->mux_bulk_rx_urb_pool[i] = usb_alloc_urb(0, GFP_KERNEL))) {
1820 +#else
1821 + if (!(odev->mux_bulk_rx_urb_pool[i] = usb_alloc_urb(0))) {
1822 +#endif
1823 + ERR("Could not allocate urb?");
1824 + return -1;
1825 + }
1826 + if (!(odev->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE, GFP_KERNEL))) {
1827 + ERR("Could not allocate buf?");
1828 + return -1;
1829 + }
1830 + }
1831 +
1832 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1833 + if (!(odev->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
1834 +#else
1835 + if (!(odev->mux_bulk_tx_urb = usb_alloc_urb(0))) {
1836 +#endif
1837 + ERR("Could not allocate urb?");
1838 + return -1;
1839 + }
1840 + if (!(odev->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL))) {
1841 + ERR("Could not allocate buf?");
1842 + return -1;
1843 + }
1844 +
1845 + return 0;
1846 +}
1847 +
1848 +/* Forward declaration */
1849 +
1850 +static int hso_serial_init(void);
1851 +static void hso_serial_exit(void);
1852 +
1853 +static void hso_net_init(struct net_device *net)
1854 +{
1855 + struct hso_priv *odev = netdev_priv(net);
1856 +
1857 + memset(odev,0,sizeof(*odev));
1858 +
1859 + D("sizeof hso_priv is %d",sizeof(*odev));
1860 +
1861 + ether_setup(net);
1862 +
1863 + SET_MODULE_OWNER(net);
1864 + net->open = hso_net_open;
1865 + net->stop = hso_net_close;
1866 +/* set config */
1867 + net->hard_start_xmit = hso_net_start_xmit;
1868 + net->do_ioctl = hso_net_ioctl;
1869 + net->get_stats = hso_net_get_stats;
1870 +/* rebuild header */
1871 + net->tx_timeout = hso_net_tx_timeout;
1872 + net->watchdog_timeo = HSO_NET_TX_TIMEOUT;
1873 +
1874 + net->flags |= IFF_NOARP;
1875 +/* features */
1876 +/* hard_header_cache */
1877 + net->set_multicast_list = hso_net_set_multicast;
1878 + net->mtu = DEFAULT_MTU - 14;
1879 + net->tx_queue_len = 10;
1880 +
1881 +/* more ethernet defaults */
1882 + odev->skb_rx_buf = NULL;
1883 + odev->rx_parse_state = WAIT_IP;
1884 + odev->wMaxSegmentSize = DEFAULT_MTU;
1885 + odev->wNumberMCFilters = 0; /* disable hardware filtering */
1886 +
1887 + spin_lock_init(&odev->net_lock);
1888 +}
1889 +
1890 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
1891 +static int hso_mux_submit_intr_urb(struct hso_priv *odev,int gfp)
1892 +#else
1893 +static int hso_mux_submit_intr_urb(struct hso_priv *odev,gfp_t gfp)
1894 +#endif
1895 +{
1896 + int res = 0;
1897 +
1898 + if (test_bit(HSO_CARD_UNPLUG, &odev->flags)) {
1899 + WARN("%s closing so not rearming mux_intr_urb", __FUNCTION__);
1900 + return 0;
1901 + }
1902 +
1903 + D5("Arm and submit the interrupt URB");
1904 +
1905 + usb_fill_int_urb(odev->mux_intr_urb,
1906 + odev->usb,
1907 + usb_rcvintpipe(odev->usb, odev->mux_ep_intr),
1908 + odev->mux_intr_buf,
1909 + MUX_INTR_BUF_SIZE,
1910 + intr_callback,
1911 + odev,
1912 + (odev->usb->speed == USB_SPEED_HIGH) ? (1 << odev->mux_bInterval) : odev->mux_bInterval);
1913 +
1914 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1915 + if ((res = usb_submit_urb(odev->mux_intr_urb, gfp))) {
1916 +#else
1917 + if ((res = usb_submit_urb(odev->mux_intr_urb))) {
1918 +#endif
1919 + WARN("%s failed mux_intr_urb %d", __FUNCTION__, res);
1920 + goto exit;
1921 + }
1922 +exit:
1923 + return res;
1924 +}
1925 +
1926 +/* AJB, called once for each unclaimed interface */
1927 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1928 +static int hso_probe(struct usb_interface *interface,
1929 + const struct usb_device_id *id)
1930 +{
1931 + struct usb_device *usb = interface_to_usbdev(interface);
1932 + unsigned int ifnum = interface->altsetting->desc.bInterfaceNumber;
1933 +#else
1934 +static void *hso_probe(struct usb_device *usb,
1935 + unsigned int ifnum,
1936 + const struct usb_device_id *id)
1937 +{
1938 + //struct usb_interface *interface= &(usb->actconfig->interface[ifnum]);
1939 + struct usb_interface *interface = usb_ifnum_to_if(usb,ifnum);
1940 +#endif
1941 + struct hso_priv *odev=NULL;
1942 + int mux = 0;
1943 + int i, res, ret=0;
1944 + struct net_device *net;
1945 + int minor, num_if;
1946 +
1947 + printk("++++++++++++++ being probed ++++++++++++++++=\n");
1948 + D1("** Start probing **");
1949 +
1950 + D1("probe called with interface num %d",ifnum);
1951 +
1952 + if (ifnum != 0) {
1953 + ret=0;
1954 + goto exit;
1955 + }
1956 +
1957 + /* Check if we found an Option 3G UMS device */
1958 + D1("Check interface num 0");
1959 + if (check_ums_and_send_rezero(usb_ifnum_to_if(usb,0), usb)) {
1960 + ret=0;
1961 + goto exit;
1962 + }
1963 +
1964 + /*
1965 + * If we get a kernel Ethernet interface, we can get our
1966 + * private data storage allocated using it
1967 + */
1968 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
1969 + net = alloc_netdev(sizeof(struct hso_priv), "hso%d", hso_net_init);
1970 + if ( !net ) {
1971 + ERR( "Unable to create ethernet device" );
1972 + ret = -ENOMEM;
1973 + goto exit;
1974 + }
1975 +
1976 + res = register_netdev(net);
1977 + if (res) {
1978 + ERR("Unable to register ethernet device");
1979 + ret = -EIO;
1980 + goto exit_freenet;
1981 + }
1982 +#else
1983 + net = alloc_etherdev(0); /* allocate memory / call init function separately */
1984 + if ( !net ) { /* since register_netdev sometimes clobbers net->priv */
1985 + ERR( "Unable to create ethernet device" );
1986 + ret = -ENOMEM;
1987 + goto exit;
1988 + }
1989 + strcpy(net->name, "hso%d");
1990 +
1991 + res = register_netdev(net);
1992 + if (res) {
1993 + ERR("Unable to register ethernet device");
1994 + ret = -EIO;
1995 + goto exit_freenet;
1996 + }
1997 +
1998 + net->priv=kzalloc(sizeof(struct hso_priv),GFP_KERNEL);
1999 + hso_net_init(net);
2000 +#endif
2001 + odev = netdev_priv(net);
2002 +
2003 + if ((num_if = check_and_claim_interfaces(usb, odev)) < 0 ) {
2004 + D1("Could not find valid interface configuration");
2005 + ret = -EIO;
2006 + goto exit_unregister;
2007 + }
2008 +
2009 + if ((res = hso_alloc_memory(odev)) ){
2010 + ret = -EIO;
2011 + goto exit_release_interfaces;
2012 + }
2013 +
2014 + usb_set_intfdata(interface, odev); /* save our data pointer in this device */
2015 + /* FIXME - should do usb_set_intfdata(interface, odev); for 1 also? */
2016 + /* FIXME - should do usb_set_intfdata(interface, odev); for 2 also? */
2017 +
2018 + /* We'll keep track of this information for later... */
2019 + odev->usb = usb;
2020 + odev->net = net;
2021 +
2022 + /* and don't forget the MAC address. */
2023 + set_ethernet_addr(odev);
2024 +
2025 + /* Send a message to syslog about what we are handling */
2026 + log_device_info(odev);
2027 +
2028 + /* Muxed ports */
2029 + for (i = 1,mux = 0; i < 0x100; i = i << 1,mux++) {
2030 + if (odev->option_info.enabled_ports & i) {
2031 + if((minor = get_free_serial_index()) < 0)
2032 + break;
2033 + hso_serial_start(odev, minor, MUX_INTERFACE, mux);
2034 + }
2035 + }
2036 +
2037 + /* Diagnostics port */
2038 + if((minor = get_free_serial_index()) >= 0) {
2039 + hso_serial_start(odev, minor, QXDM_INTERFACE, 1); /* interface num */
2040 + }
2041 +
2042 + /* C/S port */
2043 + if( ( num_if > 2 ) && ((minor = get_free_serial_index()) >= 0) ) {
2044 + hso_serial_start(odev, minor, CS_INTERFACE, 2); /* interface num */
2045 + }
2046 +
2047 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2048 + usb_get_dev(usb);
2049 +#endif
2050 +
2051 + /* Arm and submit the interrupt URB */
2052 + if(hso_mux_submit_intr_urb(odev,GFP_KERNEL) != 0) {
2053 + goto exit_release_interfaces;
2054 + }
2055 +
2056 + odev->ourproc = proc_mkdir(odev->net->name, hso_proc_dir_devices);
2057 + create_proc_read_entry("ttys", 0, odev->ourproc, hso_proc_device_ttys, odev);
2058 +
2059 + D1("** probing done **");
2060 +
2061 + ret=0;
2062 + goto exit;
2063 +
2064 +exit_release_interfaces:
2065 + /* FIXME AJB, release the usb interfaces */
2066 +
2067 +exit_unregister:
2068 + unregister_netdev(net);
2069 +
2070 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2071 +
2072 +exit_freenet:
2073 + free_netdev(net);
2074 +
2075 +exit:
2076 + return ret;
2077 +#else
2078 +
2079 +exit_freenet:
2080 + if(net->priv)
2081 + kfree(net->priv);
2082 + kfree(net);
2083 +
2084 +exit:
2085 + return ret == 0 ? odev : NULL;
2086 +#endif
2087 +}
2088 +
2089 +/*
2090 + * Module's disconnect routine
2091 + * Called when the driver is unloaded or the device is unplugged
2092 + * (Whichever happens first assuming the driver suceeded at its probe)
2093 + */
2094 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ) /* called once per interface (2.6) */
2095 +
2096 +static void hso_disconnect(struct usb_interface *interface)
2097 +{
2098 + struct usb_device *usb = interface_to_usbdev(interface);
2099 + unsigned int ifnum = interface->altsetting->desc.bInterfaceNumber;
2100 + struct hso_priv *odev;
2101 +
2102 + D1("called with interface num %d", ifnum);
2103 +
2104 + if (ifnum == 0) {
2105 +
2106 + odev = usb_get_intfdata(interface);
2107 + if (!odev || !odev->usb || !odev->net) {
2108 + WARN("odev, or odev->usb, or odev->net null");
2109 + return;
2110 + }
2111 +
2112 + /* let's cleanup our per device info */
2113 + remove_proc_entry("ttys", odev->ourproc);
2114 +
2115 + remove_proc_entry(odev->net->name, hso_proc_dir_devices);
2116 +
2117 + usb_set_intfdata(interface,NULL);
2118 +
2119 + /* stop the interrupts */
2120 + usb_kill_urb(odev->mux_intr_urb);
2121 +
2122 + /*
2123 + It is possible that this function is called before
2124 + the "close" function. This tells the close function
2125 + we are already disconnected
2126 + */
2127 + set_bit(HSO_CARD_UNPLUG, &odev->flags);
2128 +
2129 + usb_put_dev(usb);
2130 +
2131 + hso_serial_disconnect(usb, odev);
2132 +
2133 + /* release the device memory under odev */
2134 + hso_free_memory(odev);
2135 +
2136 + /* We don't need the network device any more */
2137 + unregister_netdev(odev->net);
2138 +
2139 + /* Free network device including odev memeory */
2140 + free_netdev(odev->net);
2141 +
2142 + }
2143 +
2144 + usb_driver_release_interface(&hso_driver, interface);
2145 +}
2146 +
2147 +#else /* called once per device (2.4) */
2148 +
2149 +static void hso_disconnect(struct usb_device *usb, void *ptr )
2150 +{
2151 + struct usb_interface *interface = usb_ifnum_to_if(usb,0);
2152 + struct hso_priv *odev = usb_get_intfdata(interface);
2153 + int i;
2154 +
2155 + if (!odev || !odev->usb || !odev->net) {
2156 + WARN("odev, or odev->usb, or odev->net null");
2157 + return;
2158 + }
2159 +
2160 + /* let's cleanup our per device info */
2161 + remove_proc_entry("ttys", odev->ourproc);
2162 +
2163 + remove_proc_entry(odev->net->name, hso_proc_dir_devices);
2164 +
2165 + usb_set_intfdata(interface,NULL);
2166 +
2167 + /* stop the interrupts */
2168 + usb_unlink_urb(odev->mux_intr_urb);
2169 +
2170 + /*
2171 + It is possible that this function is called before
2172 + the "close" function. This tells the close function
2173 + we are already disconnected
2174 + */
2175 + set_bit(HSO_CARD_UNPLUG, &odev->flags);
2176 +
2177 + // usb_put_dev(usb);
2178 +
2179 + hso_serial_disconnect(usb, odev);
2180 +
2181 + /* release the device memory under odev */
2182 + hso_free_memory(odev);
2183 +
2184 + /* We don't need the network device any more */
2185 + unregister_netdev(odev->net);
2186 +
2187 + /* Free network device and odev memory */
2188 + kfree(odev->net);
2189 + kfree(odev);
2190 +
2191 + for(i=0;i < usb->actconfig->bNumInterfaces;i++) {
2192 + usb_driver_release_interface(&hso_driver, usb_ifnum_to_if(usb,i));
2193 + }
2194 +}
2195 +
2196 +#endif
2197 +
2198 +static struct usb_driver hso_driver = {
2199 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2200 + .name = driver_name,
2201 + .probe = hso_probe,
2202 + .disconnect = hso_disconnect,
2203 + .id_table = hso_ids,
2204 +#else
2205 + name: driver_name,
2206 + probe: hso_probe,
2207 + disconnect: hso_disconnect,
2208 + id_table: hso_ids,
2209 +#endif
2210 +};
2211 +
2212 +int __init hso_init(void)
2213 +{
2214 + int i,rc = 0;
2215 +
2216 + D1("%s", version);
2217 +
2218 +#ifdef HSO_PROC
2219 + hso_proc_dir = proc_mkdir(driver_name, proc_root_driver);
2220 + hso_proc_dir_devices = proc_mkdir("devices", hso_proc_dir);
2221 +#endif
2222 + /* Initialise our global data */
2223 + spin_lock_init(&serial_table_lock);
2224 + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
2225 + serial_table[i] = NULL;
2226 + }
2227 +
2228 + hso_serial_init();
2229 +
2230 + if ((rc = usb_register(&hso_driver))) {
2231 + ERR("Could not register hso driver? error: %d", rc);
2232 + return rc;
2233 + }
2234 +
2235 +#ifdef HSO_PROC
2236 + create_proc_read_entry("options", 0, hso_proc_dir, hso_proc_options,NULL);
2237 +#endif
2238 + return 0;
2239 +}
2240 +
2241 +/* usb_deregister calls disconnect of registered drivers. */
2242 +void __exit hso_exit(void)
2243 +{
2244 + hso_serial_exit();
2245 +
2246 + usb_deregister(&hso_driver);
2247 +
2248 +#ifdef HSO_PROC
2249 + remove_proc_entry("options", hso_proc_dir);
2250 + remove_proc_entry("devices", hso_proc_dir);
2251 + remove_proc_entry(driver_name, proc_root_driver);
2252 +#endif
2253 +}
2254 +
2255 +/*
2256 + TTY Layer Type definitions
2257 + */
2258 +static int hso_serial_open(struct tty_struct *tty, struct file *filp);
2259 +static void hso_serial_close(struct tty_struct *tty, struct file *filp);
2260 +static void hso_serial_hangup(struct tty_struct *tty);
2261 +
2262 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2263 +static int hso_serial_write(struct tty_struct *tty, const unsigned char *buf, int count);
2264 +#else
2265 +static int hso_serial_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
2266 +#endif
2267 +
2268 +static int hso_serial_write_room(struct tty_struct *tty);
2269 +static int hso_serial_chars_in_buffer(struct tty_struct *tty);
2270 +static void hso_serial_throttle(struct tty_struct *tty);
2271 +static void hso_serial_unthrottle(struct tty_struct *tty);
2272 +static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
2273 + unsigned int cmd, unsigned long arg);
2274 +
2275 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
2276 +static void hso_serial_set_termios(struct tty_struct *tty, struct termios *old);
2277 +#else
2278 +static void hso_serial_set_termios(struct tty_struct *tty,
2279 + struct ktermios *old);
2280 +#endif
2281 +
2282 +static void hso_serial_break(struct tty_struct *tty, int break_state);
2283 +static int hso_serial_read_proc(char *page, char **start, off_t off, int count,
2284 + int *eof, void *data);
2285 +
2286 +static int hso_serial_open(struct tty_struct *tty, struct file *filp)
2287 +{
2288 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2289 + struct hso_serial *serial = get_serial_by_index(tty->index);
2290 +#else
2291 + struct hso_serial *serial = get_serial_by_index(MINOR(tty->device));
2292 +#endif
2293 + struct hso_priv *odev;
2294 +
2295 + if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) {
2296 + tty->driver_data = NULL;
2297 + ERR("Failed to open port");
2298 + return -ENODEV;
2299 + }
2300 +
2301 + down(&serial->sem);
2302 +
2303 + D1("Opening %d", serial->minor);
2304 +
2305 + tty->driver_data = serial;
2306 +
2307 + serial->tty = tty;
2308 +
2309 + odev = serial->odev;
2310 +
2311 + serial->open_count++;
2312 + if (serial->open_count == 1) {
2313 + tty->low_latency = 1;
2314 +
2315 + serial->flags = 0;
2316 +
2317 + /* Force default termio settings */
2318 + _hso_serial_set_termios(tty, NULL);
2319 +
2320 + } else {
2321 + D1("Port was already open");
2322 + }
2323 +
2324 + /* If it is not the MUX port fill in and submit a bulk urb.
2325 + (already allocated in hso_serial_start) */
2326 + if (serial->type != MUX_INTERFACE) {
2327 + int res;
2328 + usb_fill_bulk_urb(serial->rx_urb, serial->odev->usb,
2329 + usb_rcvbulkpipe(serial->odev->usb,
2330 + serial->ep_bulk_in),
2331 + serial->rx_data, serial->rx_data_length,
2332 + hso_std_serial_read_bulk_callback, serial);
2333 +
2334 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2335 + if ((res = usb_submit_urb(serial->rx_urb, GFP_KERNEL))) {
2336 +#else
2337 + if ((res = usb_submit_urb(serial->rx_urb))) {
2338 +#endif
2339 + D("Failed to submit urb - res %d", res);
2340 + }
2341 + }
2342 +
2343 + up(&serial->sem);
2344 +
2345 + return 0;
2346 +}
2347 +
2348 +static void __hso_serial_close(struct hso_serial *serial)
2349 +{
2350 + D1(" ");
2351 +
2352 + if (!serial->open_count) {
2353 + err("%s - port %d: not open", __FUNCTION__, serial->minor);
2354 + return;
2355 + }
2356 +
2357 + serial->open_count--;
2358 +
2359 + D1("serial->open_count == %d",serial->open_count);
2360 +
2361 + if (serial->open_count <= 0) {
2362 + if (serial->type != MUX_INTERFACE) {
2363 + D1("Unlink any pending bulk URBS");
2364 + /* Stop pending urbs. Do not deallocate them,
2365 + it will be done in hso_serial_stop. */
2366 + /* Is this in interrupt state? */
2367 + usb_unlink_urb(serial->rx_urb);
2368 + usb_unlink_urb(serial->tx_urb);
2369 + }
2370 + /*close ? */
2371 + serial->open_count = 0;
2372 + if (serial->tty) {
2373 + serial->tty->driver_data = NULL;
2374 + serial->tty = NULL;
2375 + }
2376 + return;
2377 + }
2378 +}
2379 +
2380 +static void hso_serial_close(struct tty_struct *tty, struct file *filp)
2381 +{
2382 + struct hso_serial *serial = NULL;
2383 + D1(" ");
2384 +
2385 + if (tty == NULL || tty->driver_data == NULL) {
2386 + D1("(tty == NULL || tty->driver_data == NULL)");
2387 + return;
2388 + }
2389 +
2390 + serial = tty->driver_data;
2391 + down(&serial->sem);
2392 + if (tty->driver_data) {
2393 + __hso_serial_close(serial);
2394 + }
2395 + up(&serial->sem);
2396 +}
2397 +
2398 +static void hso_serial_hangup(struct tty_struct *tty)
2399 +{
2400 + D1("hang up");
2401 +}
2402 +
2403 +/* Called once per device shutdown */
2404 +/* usb unused */
2405 +static void hso_serial_disconnect(struct usb_device *usb, struct hso_priv *odev)
2406 +{
2407 + struct hso_serial *serial;
2408 + int i;
2409 +
2410 + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
2411 + serial = get_serial_by_index(i);
2412 + if (serial != NULL && serial->odev == odev) { /* only close the
2413 + ports belonging to odev */
2414 + down(&serial->sem);
2415 + while (serial->open_count > 0) {
2416 + __hso_serial_close(serial);
2417 + }
2418 + hso_serial_stop(usb, i, odev);
2419 + up(&serial->sem);
2420 + }
2421 +
2422 + }
2423 +}
2424 +
2425 +
2426 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2427 +static int hso_serial_write(struct tty_struct *tty, const unsigned char *buf, int count)
2428 +#else
2429 +static int hso_serial_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
2430 +#endif
2431 +{
2432 + struct hso_serial *serial = get_serial_by_tty(tty);
2433 + int retval = -EINVAL;
2434 +
2435 + if (serial == NULL) {
2436 + ERR("%s(%d) tty or tty->driver_data is NULL", __FUNCTION__,
2437 + __LINE__);
2438 + return -ENODEV;
2439 + }
2440 +
2441 + down(&serial->sem);
2442 +
2443 + while (test_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags)) {
2444 + /* wait for previous write to complete
2445 + * how else to ensure we are always able
2446 + * to write at least one byte for putchar()? */
2447 + D2("HSO_SERIAL_FLAG_TX_SENT says already in progress");
2448 + udelay(500);
2449 + }
2450 +
2451 + set_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags);
2452 +
2453 + D2(" hso_port = %d count %d", serial->minor, count);
2454 + count = min((u16) count, serial->tx_data_length);
2455 +
2456 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2457 + memcpy(serial->tx_data, buf, count);
2458 +#else
2459 + if (from_user) {
2460 + if (copy_from_user(serial->tx_data, buf, count)) {
2461 + ERR("copy_from_user() failed");
2462 + }
2463 + } else {
2464 + memcpy (serial->tx_data, buf, count);
2465 + }
2466 +#endif
2467 +
2468 + serial->tx_data_count = count;
2469 +
2470 + if (serial->write_data) {
2471 + retval = serial->write_data(serial);
2472 + } else {
2473 + clear_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags);
2474 + retval = -ENODEV;
2475 + }
2476 +
2477 + up(&serial->sem);
2478 + return retval;
2479 +}
2480 +
2481 +static int hso_mux_serial_write_data(struct hso_serial *serial)
2482 +{
2483 + return mux_device_request(serial,
2484 + SEND_ENCAPSULATED_COMMAND,
2485 + serial->mux,
2486 + serial->tx_urb,
2487 + &serial->ctrl_req_tx,
2488 + serial->tx_data, serial->tx_data_count);
2489 +}
2490 +
2491 +static int hso_std_serial_write_data(struct hso_serial *serial)
2492 +{
2493 + int count = serial->tx_data_count;
2494 + int res;
2495 +
2496 + usb_fill_bulk_urb(serial->tx_urb,
2497 + serial->odev->usb,
2498 + usb_sndbulkpipe(serial->odev->usb,
2499 + serial->ep_bulk_out),
2500 + serial->tx_data,
2501 + serial->tx_data_count,
2502 + hso_std_serial_write_bulk_callback,
2503 + serial);
2504 +
2505 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2506 + if ((res = usb_submit_urb(serial->tx_urb, GFP_KERNEL))) {
2507 +#else
2508 + if ((res = usb_submit_urb(serial->tx_urb))) {
2509 +#endif
2510 + D("Failed to submit urb - res %d ", res);
2511 + clear_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags);
2512 + return res;
2513 + }
2514 +
2515 + return count;
2516 +}
2517 +
2518 +static int hso_serial_write_room(struct tty_struct *tty)
2519 +{
2520 + struct hso_serial *serial = get_serial_by_tty(tty);
2521 + int room = 0;
2522 +
2523 + if (serial == NULL)
2524 + return 0;
2525 +
2526 + down(&serial->sem);
2527 +
2528 + if(!test_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags))
2529 + room = serial->tx_data_length;
2530 +
2531 + up(&serial->sem);
2532 +
2533 + D4("room = %d ", room);
2534 +
2535 + return room;
2536 +}
2537 +
2538 +static int hso_serial_chars_in_buffer(struct tty_struct *tty)
2539 +{
2540 + struct hso_serial *serial = get_serial_by_tty(tty);
2541 + int chars = 0;
2542 +
2543 + if (serial == NULL) {
2544 + return 0;
2545 + }
2546 +
2547 + down(&serial->sem);
2548 +
2549 + if(test_bit(HSO_SERIAL_FLAG_TX_SENT, &serial->flags))
2550 + chars = serial->tx_urb->transfer_buffer_length;
2551 +
2552 + up(&serial->sem);
2553 +
2554 + D4("chars = %d ", chars);
2555 +
2556 + return chars;
2557 +}
2558 +
2559 +static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
2560 +{
2561 + struct tty_struct *tty = serial->tty;
2562 +
2563 + if (urb == NULL || serial == NULL) {
2564 + D1("serial = NULL");
2565 + return;
2566 + }
2567 +
2568 + /* Push data to tty */
2569 + if (tty && urb->actual_length) {
2570 +
2571 +
2572 + D("data to push to tty");
2573 +
2574 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) )
2575 + {
2576 + int i;
2577 + unsigned char *data = urb->transfer_buffer;
2578 +
2579 + for (i = 0; i < urb->actual_length ; ++i) {
2580 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
2581 + tty_flip_buffer_push(tty);
2582 + tty_insert_flip_char(tty, data[i], 0);
2583 + }
2584 + tty_flip_buffer_push(tty);
2585 + }
2586 +#else
2587 + tty_buffer_request_room(tty, urb->actual_length);
2588 + tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
2589 + tty_flip_buffer_push(tty);
2590 +#endif
2591 + }
2592 +
2593 +#if 0
2594 + /* FIXME - AJB, maybe we need to throttle? */
2595 +
2596 + if (rx_fifo->cnt >= HSO_THRESHOLD_THROTTLE
2597 + && !test_and_set_bit(HSO_SERIAL_FLAG_THROTTLED, &serial->flags)) {
2598 + D1("Throttle: rx_fifo->cnt[%d] >= HSO_THRESHOLD_THROTTLE[%d]",
2599 + rx_fifo->cnt, HSO_THRESHOLD_THROTTLE);
2600 +/* hss_throttle(port); */
2601 + }
2602 +#endif
2603 +
2604 +}
2605 +
2606 +static void hso_serial_throttle(struct tty_struct *tty)
2607 +{
2608 + D1(" ");
2609 +}
2610 +
2611 +static void hso_serial_unthrottle(struct tty_struct *tty)
2612 +{
2613 + D1(" ");
2614 +}
2615 +
2616 +static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
2617 + unsigned int cmd, unsigned long arg)
2618 +{
2619 + D4(" ");
2620 + return -ENOIOCTLCMD;
2621 +}
2622 +
2623 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
2624 +static void _hso_serial_set_termios(struct tty_struct *tty,
2625 + struct termios *old)
2626 +#else
2627 +static void _hso_serial_set_termios(struct tty_struct *tty,
2628 + struct ktermios *old)
2629 +#endif
2630 +{
2631 + struct hso_serial *serial = get_serial_by_tty(tty);
2632 +
2633 + if ((!tty) || (!tty->termios) || (!serial)) {
2634 + ERR("no tty structures");
2635 + return;
2636 + }
2637 +
2638 + D4("port %d", serial->minor);
2639 +
2640 + /*
2641 + * The default requirements for this device are:
2642 + */
2643 + serial->tty->termios->c_iflag &= ~(IGNBRK /* disable ignore break */
2644 + | BRKINT /* disable break causes interrupt */
2645 + | PARMRK /* disable mark parity errors */
2646 + | ISTRIP /* disable clear high bit of input characters */
2647 + | INLCR /* disable translate NL to CR */
2648 + | IGNCR /* disable ignore CR */
2649 + | ICRNL /* disable translate CR to NL */
2650 + | IXON); /* disable enable XON/XOFF flow control */
2651 +
2652 + serial->tty->termios->c_oflag &= ~OPOST; /* disable postprocess output characters */
2653 +
2654 + serial->tty->termios->c_lflag &= ~(ECHO /* disable echo input characters */
2655 + | ECHONL /* disable echo new line */
2656 + | ICANON /* disable erase, kill, werase, and rprnt special characters */
2657 + | ISIG /* disable interrupt, quit, and suspend special characters */
2658 + | IEXTEN); /* disable non-POSIX special characters */
2659 +
2660 + serial->tty->termios->c_cflag &= ~(CSIZE /* no size */
2661 + | PARENB /* disable parity bit */
2662 + | CBAUD); /* clear current baud rate */
2663 +
2664 + serial->tty->termios->c_cflag |= (CS8 /* character size 8 bits */
2665 + | B115200); /* baud rate 115200 */
2666 +
2667 + /*
2668 + * Force low_latency on; otherwise the pushes are scheduled;
2669 + * this is bad as it opens up the possibility of dropping bytes
2670 + * on the floor. We don't want to drop bytes on the floor. :)
2671 + */
2672 + serial->tty->low_latency = 1;
2673 +
2674 + /* Notify the tty driver that the termios have changed. */
2675 + serial->tty->ldisc.set_termios(serial->tty, NULL);
2676 + return;
2677 +}
2678 +
2679 +/*
2680 + * TODO - need to be down/up protected, but currently it is also used in serial_open
2681 + * also locking it...
2682 + */
2683 +
2684 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
2685 +static void hso_serial_set_termios(struct tty_struct *tty, struct termios *old)
2686 +#else
2687 +static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)
2688 +#endif
2689 +{
2690 + struct hso_serial *serial = get_serial_by_tty(tty);
2691 +
2692 + if ((!tty) || (!tty->termios) || (!serial)) {
2693 + D1("no tty structures");
2694 + return;
2695 + }
2696 +
2697 + D1("port %d", serial->minor);
2698 +
2699 + down(&serial->sem);
2700 + if (serial->open_count)
2701 + _hso_serial_set_termios(tty, old);
2702 + up(&serial->sem);
2703 +
2704 + return;
2705 +}
2706 +
2707 +static void hso_serial_break(struct tty_struct *tty, int break_state)
2708 +{
2709 + D1(" ");
2710 +}
2711 +
2712 +static int hso_serial_read_proc(char *page, char **start, off_t off, int count,
2713 + int *eof, void *data)
2714 +{
2715 + return 0;
2716 +}
2717 +
2718 +#if 0
2719 +static void port_softint(void *private)
2720 +{
2721 + struct hso_serial *serial = (struct hso_serial *) private;
2722 + struct tty_struct *tty;
2723 +
2724 + D1(" - port %d", serial->minor);
2725 +
2726 + if (!serial)
2727 + return;
2728 +
2729 + tty = serial->tty;
2730 + if (!tty)
2731 + return;
2732 +
2733 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
2734 + && tty->ldisc.write_wakeup) {
2735 + D1(" - write wakeup call.");
2736 + (tty->ldisc.write_wakeup) (tty);
2737 + }
2738 +
2739 + wake_up_interruptible(&tty->write_wait);
2740 +}
2741 +#endif
2742 +
2743 +static struct hso_serial *hso_serial_start(struct hso_priv *odev, u8 minor, enum type_intf type, u8 num)
2744 +{
2745 + struct hso_serial *serial = NULL;
2746 +
2747 + if (!(serial = kmalloc(sizeof(*serial), GFP_KERNEL))) {
2748 + ERR("%s - Out of memory", __FUNCTION__);
2749 + return NULL;
2750 + }
2751 +
2752 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2753 + D1("tty_register_device %d", minor);
2754 + tty_register_device(tty_drv, minor, NULL);
2755 +#endif
2756 +
2757 + serial->odev = odev;
2758 + serial->minor = minor;
2759 + serial->type = type;
2760 + serial->mux = (type == MUX_INTERFACE) ? num : 0;
2761 + serial->magic = HSO_SERIAL_MAGIC;
2762 +
2763 + serial->rx_urb = NULL;
2764 + serial->rx_data = NULL;
2765 + serial->rx_data_length = 0;
2766 +
2767 + switch(type) {
2768 + case MUX_INTERFACE:
2769 + switch(num) {
2770 + case 0:
2771 + QFO("Multiplexed Control channel present");
2772 + break;
2773 + case 1:
2774 + QFO("Multiplexed Application channel present");
2775 + break;
2776 + case 2:
2777 + QFO("Multiplexed PC/SC channel present");
2778 + break;
2779 + case 3:
2780 + QFO("Multiplexed GPS channel present");
2781 + break;
2782 + case 4:
2783 + QFO("Multiplexed Application 2 channel present");
2784 + break;
2785 + case 5:
2786 + case 6:
2787 + case 7:
2788 + QFO("Multiplexed Reserved(%d) channel present",num);
2789 + break;
2790 + }
2791 + break;
2792 + case QXDM_INTERFACE:
2793 + QFO("QXDM port present");
2794 + break;
2795 + case CS_INTERFACE:
2796 + QFO("Circuit Switched port present");
2797 + break;
2798 + }
2799 +
2800 + if (type != MUX_INTERFACE) {
2801 + if (get_std_serial_endpoints(usb_ifnum_to_if(odev->usb,num), serial)) {
2802 + D1("Interface endpoints did not suit us");
2803 + goto exit;
2804 + }
2805 + }
2806 +
2807 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2808 + if (!(serial->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
2809 +#else
2810 + if (!(serial->rx_urb = usb_alloc_urb(0))) {
2811 +#endif
2812 + ERR("Could not allocate urb?");
2813 + goto exit;
2814 + }
2815 + serial->rx_urb->transfer_buffer = NULL;
2816 + serial->rx_urb->transfer_buffer_length = 0;
2817 +
2818 + serial->rx_data_length =
2819 + (type == MUX_INTERFACE) ? CTRL_URB_RX_SIZE : BULK_URB_RX_SIZE;
2820 +
2821 + if (!(serial->rx_data = kzalloc(serial->rx_data_length, GFP_KERNEL))) {
2822 + ERR("%s - Out of memory", __FUNCTION__);
2823 + goto exit;
2824 + }
2825 +
2826 + serial->tx_data_length = 0;
2827 + serial->tx_data_count = 0;
2828 + serial->tx_data = NULL;
2829 + serial->tx_urb = NULL;
2830 +
2831 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2832 + if (!(serial->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
2833 +#else
2834 + if (!(serial->tx_urb = usb_alloc_urb(0))) {
2835 +#endif
2836 + ERR("Could not allocate urb?");
2837 + goto exit;
2838 + }
2839 + serial->tx_urb->transfer_buffer = NULL;
2840 + serial->tx_urb->transfer_buffer_length = 0;
2841 +
2842 + serial->tx_data_length =
2843 + (type == MUX_INTERFACE) ? CTRL_URB_TX_SIZE : BULK_URB_TX_SIZE;
2844 +
2845 + if (!(serial->tx_data = kzalloc(serial->tx_data_length, GFP_KERNEL))) {
2846 + ERR("%s - Out of memory", __FUNCTION__);
2847 + goto exit;
2848 + }
2849 +
2850 + /* The muxed ports can not use full 64 bytes and the diagnostic must use
2851 + * the full 64 bytes if sending larger packets. */
2852 + if (type == MUX_INTERFACE)
2853 + serial->tx_data_length--;
2854 +
2855 + if (type == MUX_INTERFACE) {
2856 + serial->write_data = hso_mux_serial_write_data;
2857 + } else {
2858 + serial->write_data = hso_std_serial_write_data;
2859 + }
2860 +
2861 + serial->open_count = 0;
2862 + serial->private = NULL;
2863 + init_MUTEX(&serial->sem);
2864 +
2865 + set_serial_by_index(minor,serial);
2866 +
2867 + return serial;
2868 +
2869 + exit:
2870 + if (serial->rx_urb) {
2871 + usb_free_urb(serial->rx_urb);
2872 + }
2873 + if (serial->rx_data) {
2874 + kfree(serial->rx_data);
2875 + }
2876 + if (serial->tx_data) {
2877 + kfree(serial->tx_data);
2878 + }
2879 + if (serial->tx_urb) {
2880 + usb_free_urb(serial->tx_urb);
2881 + }
2882 +
2883 + if (serial) {
2884 + kfree(serial);
2885 + }
2886 + return NULL;
2887 +}
2888 +
2889 +/* release the serial port */
2890 +static void hso_serial_stop(struct usb_device *dev, u8 minor,
2891 + struct hso_priv *odev)
2892 +{
2893 + struct hso_serial *serial;
2894 +
2895 + D1("Deregistering serial %d", minor);
2896 +
2897 + serial = get_serial_by_index(minor);
2898 + if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) {
2899 + ERR("Trying to deregister an unused serial port");
2900 + return;
2901 + }
2902 +
2903 + if (serial->odev != odev) {
2904 + ERR("Trying to deregister a serial port belonging to a different device");
2905 + return;
2906 + }
2907 +
2908 + serial->odev = NULL;
2909 + serial->minor = 0;
2910 + serial->mux = 0;
2911 + serial->magic = 0;
2912 +
2913 + serial->write_data = NULL;
2914 +
2915 + if (serial->rx_urb != NULL) {
2916 + usb_unlink_urb(serial->rx_urb);
2917 + usb_free_urb(serial->rx_urb);
2918 + }
2919 + serial->rx_urb = NULL;
2920 +
2921 + if (serial->rx_data != NULL)
2922 + kfree(serial->rx_data);
2923 + serial->rx_data = NULL;
2924 +
2925 + if (serial->tx_urb != NULL) {
2926 + usb_unlink_urb(serial->tx_urb);
2927 + usb_free_urb(serial->tx_urb);
2928 + }
2929 + serial->tx_urb = NULL;
2930 +
2931 + if (serial->tx_data != NULL)
2932 + kfree(serial->tx_data);
2933 + serial->tx_data = NULL;
2934 +
2935 + kfree(serial);
2936 + serial = NULL;
2937 +
2938 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2939 + tty_unregister_device(tty_drv,minor);
2940 +#endif
2941 +
2942 + set_serial_by_index(minor,NULL);
2943 +}
2944 +
2945 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) )
2946 +
2947 +#else
2948 +static struct tty_operations hso_serial_ops = {
2949 + .open = hso_serial_open,
2950 + .close = hso_serial_close,
2951 + .write = hso_serial_write,
2952 + .write_room = hso_serial_write_room,
2953 + .ioctl = hso_serial_ioctl,
2954 + .set_termios = hso_serial_set_termios,
2955 + .throttle = hso_serial_throttle,
2956 + .unthrottle = hso_serial_unthrottle,
2957 + .break_ctl = hso_serial_break,
2958 + .chars_in_buffer = hso_serial_chars_in_buffer,
2959 + .read_proc = hso_serial_read_proc,
2960 + /* .tiocmget = serial_tiocmget, */
2961 + /* .tiocmset = serial_tiocmset, */
2962 + .hangup = hso_serial_hangup,
2963 +};
2964 +
2965 +#endif
2966 +
2967 +
2968 +/* AJB, called by hso_init() once per load */
2969 +static int hso_serial_init(void)
2970 +{
2971 + int result;
2972 + D1("Starting hso_serial");
2973 +
2974 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2975 + tty_drv = alloc_tty_driver(HSO_SERIAL_TTY_MINORS);
2976 +#else
2977 + tty_drv = kzalloc(sizeof(*tty_drv),GFP_KERNEL);
2978 +#endif
2979 + if (!tty_drv)
2980 + return -ENOMEM;
2981 +
2982 + /* register the tty driver */
2983 + tty_drv->magic = TTY_DRIVER_MAGIC;
2984 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
2985 + tty_drv->owner = THIS_MODULE;
2986 + tty_drv->name = "ttyHS";
2987 +#else
2988 + tty_drv->name = "usb/tth/%d";
2989 +#endif
2990 + tty_drv->driver_name = "hso";
2991 +
2992 +#ifdef HSO_SERIAL_TTY_MAJOR
2993 + tty_drv->major = HSO_SERIAL_TTY_MAJOR;
2994 +#endif
2995 + tty_drv->minor_start = 0;
2996 + tty_drv->num = HSO_SERIAL_TTY_MINORS; /* FIXME - can we get away without this here? */
2997 +
2998 + tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
2999 + tty_drv->subtype = SERIAL_TYPE_NORMAL;
3000 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) )
3001 + //tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
3002 + tty_drv->flags = TTY_DRIVER_REAL_RAW;
3003 +#else
3004 + tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
3005 +#endif
3006 +
3007 + tty_drv->init_termios = tty_std_termios;
3008 + tty_drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
3009 +
3010 + tty_drv->termios = hso_serial_termios;
3011 + tty_drv->termios_locked = hso_serial_termios_locked;
3012 +
3013 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) )
3014 + tty_drv->refcount = &hso_serial_refcount;
3015 + tty_drv->table = hso_serial_tty;
3016 +#endif
3017 +
3018 +
3019 +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) )
3020 +
3021 + tty_drv->open = hso_serial_open;
3022 + tty_drv->close = hso_serial_close;
3023 + tty_drv->write = hso_serial_write;
3024 + tty_drv->write_room = hso_serial_write_room;
3025 + tty_drv->ioctl = hso_serial_ioctl;
3026 + tty_drv->set_termios = hso_serial_set_termios;
3027 + tty_drv->throttle = hso_serial_throttle;
3028 + tty_drv->unthrottle = hso_serial_unthrottle;
3029 + tty_drv->break_ctl = hso_serial_break;
3030 + tty_drv->chars_in_buffer = hso_serial_chars_in_buffer;
3031 + tty_drv->read_proc = hso_serial_read_proc;
3032 + /* tty_drv->tiocmget = serial_tiocmget; */
3033 + /* tty_drv->tiocmset = serial_tiocmset; */
3034 + tty_drv->hangup = hso_serial_hangup;
3035 +
3036 +#else
3037 + tty_set_operations(tty_drv, &hso_serial_ops);
3038 +#endif
3039 +
3040 + result = tty_register_driver(tty_drv);
3041 + if (result) {
3042 + ERR("tty_register_driver failed(%d)",result);
3043 + return result;
3044 + }
3045 +
3046 + D1("end hso_serial");
3047 +
3048 + return 0;
3049 +}
3050 +
3051 +/* AJB, called by hso_exit() once per unload */
3052 +static void hso_serial_exit(void)
3053 +{
3054 + struct hso_serial *serial = NULL;
3055 + int i;
3056 + int result;
3057 +
3058 + D1("Stopping hso_serial");
3059 +
3060 + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
3061 + serial = get_serial_by_index(i);
3062 + if (serial != NULL) {
3063 + down(&serial->sem);
3064 + while (serial->open_count > 0) {
3065 + __hso_serial_close(serial);
3066 + }
3067 + hso_serial_stop(serial->odev->usb, i, serial->odev);
3068 + up(&serial->sem);
3069 + }
3070 + }
3071 +
3072 + result = tty_unregister_driver(tty_drv);
3073 + if (result) {
3074 + err("%s - tty_unregister_driver failed(%d)", __FUNCTION__,result);
3075 + }
3076 +}
3077 +
3078 +/*
3079 + * Module definitions
3080 + */
3081 +module_init(hso_init);
3082 +module_exit(hso_exit);
3083 +
3084 +MODULE_AUTHOR(MOD_AUTHOR);
3085 +MODULE_DESCRIPTION("USB High Speed Option driver");
3086 +MODULE_LICENSE("GPL");
3087 +
3088 +MODULE_DEVICE_TABLE(usb, hso_ids);
3089 +
3090 +MODULE_PARM_DESC(debug, "Level of debug [0x01 | 0x02 | 0x04 | 0x08]");
3091 +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) )
3092 +module_param(debug, int, S_IRUGO | S_IWUSR);
3093 +#else
3094 +MODULE_PARM(debug, "i");
3095 +#endif
3096 +
3097 diff --exclude=CVS -Nur linux-2.4.36.6.orig/drivers/char/pcmcia/hso/Makefile linux-2.4.36.6/drivers/char/pcmcia/hso/Makefile
3098 --- linux-2.4.36.6.orig/drivers/char/pcmcia/hso/Makefile 1970-01-01 01:00:00.000000000 +0100
3099 +++ linux-2.4.36.6/drivers/char/pcmcia/hso/Makefile 2008-07-30 14:30:57.000000000 +0200
3100 @@ -0,0 +1,2 @@
3101 +obj-m += hso.o
3102 +include $(TOPDIR)/Rules.make
3103 diff --exclude=CVS -Nur linux-2.4.36.6.orig/drivers/char/pcmcia/Makefile linux-2.4.36.6/drivers/char/pcmcia/Makefile
3104 --- linux-2.4.36.6.orig/drivers/char/pcmcia/Makefile 2008-06-06 18:25:34.000000000 +0200
3105 +++ linux-2.4.36.6/drivers/char/pcmcia/Makefile 2008-07-30 12:52:08.000000000 +0200
3106 @@ -18,4 +18,8 @@
3107 obj-$(CONFIG_PCMCIA_SERIAL_CS) += serial_cs.o
3108 obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o
3109
3110 +# Object files in subdirectories
3111 +mod-subdirs := hso
3112 +subdir-y += hso
3113 +
3114 include $(TOPDIR)/Rules.make

root@freewrt.org:443
ViewVC Help
Powered by ViewVC 1.1.20