diff options
Diffstat (limited to 'drivers/usb')
171 files changed, 17841 insertions, 15224 deletions
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 90583d6a5949..507a9bd0d77c 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -1052,7 +1052,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, instance->usbatm = usbatm_instance; instance->modem_type = (struct cxacru_modem_type *) id->driver_info; - memset(instance->card_info, 0, sizeof(instance->card_info)); mutex_init(&instance->poll_state_serialize); instance->poll_state = CXPOLL_STOPPED; diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 7d27c9cf3c43..76fce44c2f9a 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -829,7 +829,6 @@ static int speedtch_bind(struct usbatm_data *usbatm, if (use_isoc) { const struct usb_host_interface *desc = data_intf->cur_altsetting; const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in; - int i; use_isoc = 0; /* fall back to bulk if endpoint not found */ diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index c3201affa0b6..0725b1871f23 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -159,12 +159,34 @@ static void acm_write_done(struct acm *acm, struct acm_wb *wb) spin_lock_irqsave(&acm->write_lock, flags); acm->write_ready = 1; wb->use = 0; + acm->transmitting--; spin_unlock_irqrestore(&acm->write_lock, flags); } /* * Poke write. + * + * the caller is responsible for locking */ + +static int acm_start_wb(struct acm *acm, struct acm_wb *wb) +{ + int rc; + + acm->transmitting++; + + wb->urb->transfer_buffer = wb->buf; + wb->urb->transfer_dma = wb->dmah; + wb->urb->transfer_buffer_length = wb->len; + wb->urb->dev = acm->dev; + + if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) { + dbg("usb_submit_urb(write bulk) failed: %d", rc); + acm_write_done(acm, wb); + } + return rc; +} + static int acm_write_start(struct acm *acm, int wbn) { unsigned long flags; @@ -182,26 +204,31 @@ static int acm_write_start(struct acm *acm, int wbn) return 0; /* A white lie */ } + wb = &acm->wb[wbn]; + if(acm_wb_is_avail(acm) <= 1) + acm->write_ready = 0; + + dbg("%s susp_count: %d", __func__, acm->susp_count); + if (acm->susp_count) { + acm->old_ready = acm->write_ready; + acm->delayed_wb = wb; + acm->write_ready = 0; + schedule_work(&acm->waker); + spin_unlock_irqrestore(&acm->write_lock, flags); + return 0; /* A white lie */ + } + usb_mark_last_busy(acm->dev); + if (!acm_wb_is_used(acm, wbn)) { spin_unlock_irqrestore(&acm->write_lock, flags); return 0; } - wb = &acm->wb[wbn]; - if(acm_wb_is_avail(acm) <= 1) - acm->write_ready = 0; + rc = acm_start_wb(acm, wb); spin_unlock_irqrestore(&acm->write_lock, flags); - wb->urb->transfer_buffer = wb->buf; - wb->urb->transfer_dma = wb->dmah; - wb->urb->transfer_buffer_length = wb->len; - wb->urb->dev = acm->dev; - - if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) { - dbg("usb_submit_urb(write bulk) failed: %d", rc); - acm_write_done(acm, wb); - } return rc; + } /* * attributes exported through sysfs @@ -304,6 +331,7 @@ static void acm_ctrl_irq(struct urb *urb) break; } exit: + usb_mark_last_busy(acm->dev); retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -320,8 +348,11 @@ static void acm_read_bulk(struct urb *urb) dbg("Entering acm_read_bulk with status %d", status); - if (!ACM_READY(acm)) + if (!ACM_READY(acm)) { + dev_dbg(&acm->data->dev, "Aborting, acm not ready"); return; + } + usb_mark_last_busy(acm->dev); if (status) dev_dbg(&acm->data->dev, "bulk rx status %d\n", status); @@ -331,6 +362,7 @@ static void acm_read_bulk(struct urb *urb) if (likely(status == 0)) { spin_lock(&acm->read_lock); + acm->processing++; list_add_tail(&rcv->list, &acm->spare_read_urbs); list_add_tail(&buf->list, &acm->filled_read_bufs); spin_unlock(&acm->read_lock); @@ -343,7 +375,8 @@ static void acm_read_bulk(struct urb *urb) /* nevertheless the tasklet must be kicked unconditionally so the queue cannot dry up */ } - tasklet_schedule(&acm->urb_task); + if (likely(!acm->susp_count)) + tasklet_schedule(&acm->urb_task); } static void acm_rx_tasklet(unsigned long _acm) @@ -354,16 +387,23 @@ static void acm_rx_tasklet(unsigned long _acm) struct acm_ru *rcv; unsigned long flags; unsigned char throttled; + dbg("Entering acm_rx_tasklet"); if (!ACM_READY(acm)) + { + dbg("acm_rx_tasklet: ACM not ready"); return; + } spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (throttled) + { + dbg("acm_rx_tasklet: throttled"); return; + } next_buffer: spin_lock_irqsave(&acm->read_lock, flags); @@ -403,6 +443,7 @@ urbs: while (!list_empty(&acm->spare_read_bufs)) { spin_lock_irqsave(&acm->read_lock, flags); if (list_empty(&acm->spare_read_urbs)) { + acm->processing = 0; spin_unlock_irqrestore(&acm->read_lock, flags); return; } @@ -425,18 +466,23 @@ urbs: rcv->urb->transfer_dma = buf->dma; rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf); - /* This shouldn't kill the driver as unsuccessful URBs are returned to the free-urbs-pool and resubmited ASAP */ - if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { + spin_lock_irqsave(&acm->read_lock, flags); + if (acm->susp_count || usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { list_add(&buf->list, &acm->spare_read_bufs); - spin_lock_irqsave(&acm->read_lock, flags); list_add(&rcv->list, &acm->spare_read_urbs); + acm->processing = 0; spin_unlock_irqrestore(&acm->read_lock, flags); return; + } else { + spin_unlock_irqrestore(&acm->read_lock, flags); + dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf); } } + spin_lock_irqsave(&acm->read_lock, flags); + acm->processing = 0; + spin_unlock_irqrestore(&acm->read_lock, flags); } /* data interface wrote those outgoing bytes */ @@ -463,6 +509,27 @@ static void acm_softint(struct work_struct *work) tty_wakeup(acm->tty); } +static void acm_waker(struct work_struct *waker) +{ + struct acm *acm = container_of(waker, struct acm, waker); + long flags; + int rv; + + rv = usb_autopm_get_interface(acm->control); + if (rv < 0) { + err("Autopm failure in %s", __func__); + return; + } + if (acm->delayed_wb) { + acm_start_wb(acm, acm->delayed_wb); + acm->delayed_wb = NULL; + } + spin_lock_irqsave(&acm->write_lock, flags); + acm->write_ready = acm->old_ready; + spin_unlock_irqrestore(&acm->write_lock, flags); + usb_autopm_put_interface(acm->control); +} + /* * TTY handlers */ @@ -492,6 +559,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) if (usb_autopm_get_interface(acm->control) < 0) goto early_bail; + else + acm->control->needs_remote_wakeup = 1; mutex_lock(&acm->mutex); if (acm->used++) { @@ -509,6 +578,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && (acm->ctrl_caps & USB_CDC_CAP_LINE)) goto full_bailout; + usb_autopm_put_interface(acm->control); INIT_LIST_HEAD(&acm->spare_read_urbs); INIT_LIST_HEAD(&acm->spare_read_bufs); @@ -570,12 +640,14 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) mutex_lock(&open_mutex); if (!--acm->used) { if (acm->dev) { + usb_autopm_get_interface(acm->control); acm_set_control(acm, acm->ctrlout = 0); usb_kill_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_kill_urb(acm->wb[i].urb); for (i = 0; i < nr; i++) usb_kill_urb(acm->ru[i].urb); + acm->control->needs_remote_wakeup = 0; usb_autopm_put_interface(acm->control); } else acm_tty_unregister(acm); @@ -660,13 +732,16 @@ static void acm_tty_unthrottle(struct tty_struct *tty) tasklet_schedule(&acm->urb_task); } -static void acm_tty_break_ctl(struct tty_struct *tty, int state) +static int acm_tty_break_ctl(struct tty_struct *tty, int state) { struct acm *acm = tty->driver_data; + int retval; if (!ACM_READY(acm)) - return; - if (acm_send_break(acm, state ? 0xffff : 0)) + return -EINVAL; + retval = acm_send_break(acm, state ? 0xffff : 0); + if (retval < 0) dbg("send break failed"); + return retval; } static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file) @@ -766,7 +841,7 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios * USB probe and disconnect routines. */ -/* Little helper: write buffers free */ +/* Little helpers: write/read buffers free */ static void acm_write_buffers_free(struct acm *acm) { int i; @@ -777,6 +852,15 @@ static void acm_write_buffers_free(struct acm *acm) } } +static void acm_read_buffers_free(struct acm *acm) +{ + struct usb_device *usb_dev = interface_to_usbdev(acm->control); + int i, n = acm->rx_buflimit; + + for (i = 0; i < n; i++) + usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); +} + /* Little helper: write buffers allocate */ static int acm_write_buffers_alloc(struct acm *acm) { @@ -987,6 +1071,7 @@ skip_normal_probe: acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint); + INIT_WORK(&acm->waker, acm_waker); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); @@ -1098,8 +1183,7 @@ alloc_fail8: for (i = 0; i < ACM_NW; i++) usb_free_urb(acm->wb[i].urb); alloc_fail7: - for (i = 0; i < num_rx_buf; i++) - usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); + acm_read_buffers_free(acm); for (i = 0; i < num_rx_buf; i++) usb_free_urb(acm->ru[i].urb); usb_free_urb(acm->ctrlurb); @@ -1116,6 +1200,7 @@ alloc_fail: static void stop_data_traffic(struct acm *acm) { int i; + dbg("Entering stop_data_traffic"); tasklet_disable(&acm->urb_task); @@ -1128,21 +1213,16 @@ static void stop_data_traffic(struct acm *acm) tasklet_enable(&acm->urb_task); cancel_work_sync(&acm->work); + cancel_work_sync(&acm->waker); } static void acm_disconnect(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); struct usb_device *usb_dev = interface_to_usbdev(intf); - int i; - - if (!acm || !acm->dev) { - dbg("disconnect on nonexisting interface"); - return; - } mutex_lock(&open_mutex); - if (!usb_get_intfdata(intf)) { + if (!acm || !acm->dev) { mutex_unlock(&open_mutex); return; } @@ -1161,10 +1241,10 @@ static void acm_disconnect(struct usb_interface *intf) acm_write_buffers_free(acm); usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); - for (i = 0; i < acm->rx_buflimit; i++) - usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); + acm_read_buffers_free(acm); - usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf); + usb_driver_release_interface(&acm_driver, intf == acm->control ? + acm->data : acm->control); if (!acm->used) { acm_tty_unregister(acm); @@ -1178,11 +1258,31 @@ static void acm_disconnect(struct usb_interface *intf) tty_hangup(acm->tty); } +#ifdef CONFIG_PM static int acm_suspend(struct usb_interface *intf, pm_message_t message) { struct acm *acm = usb_get_intfdata(intf); + int cnt; + + if (acm->dev->auto_pm) { + int b; + + spin_lock_irq(&acm->read_lock); + spin_lock(&acm->write_lock); + b = acm->processing + acm->transmitting; + spin_unlock(&acm->write_lock); + spin_unlock_irq(&acm->read_lock); + if (b) + return -EBUSY; + } + + spin_lock_irq(&acm->read_lock); + spin_lock(&acm->write_lock); + cnt = acm->susp_count++; + spin_unlock(&acm->write_lock); + spin_unlock_irq(&acm->read_lock); - if (acm->susp_count++) + if (cnt) return 0; /* we treat opened interfaces differently, @@ -1201,15 +1301,21 @@ static int acm_resume(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); int rv = 0; + int cnt; + + spin_lock_irq(&acm->read_lock); + acm->susp_count -= 1; + cnt = acm->susp_count; + spin_unlock_irq(&acm->read_lock); - if (--acm->susp_count) + if (cnt) return 0; mutex_lock(&acm->mutex); if (acm->used) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); if (rv < 0) - goto err_out; + goto err_out; tasklet_schedule(&acm->urb_task); } @@ -1218,6 +1324,8 @@ err_out: mutex_unlock(&acm->mutex); return rv; } + +#endif /* CONFIG_PM */ /* * USB driver structure. */ @@ -1273,10 +1381,14 @@ static struct usb_driver acm_driver = { .name = "cdc_acm", .probe = acm_probe, .disconnect = acm_disconnect, +#ifdef CONFIG_PM .suspend = acm_suspend, .resume = acm_resume, +#endif .id_table = acm_ids, +#ifdef CONFIG_PM .supports_autosuspend = 1, +#endif }; /* diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 046e064b033a..85c3aaaab7c5 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -107,10 +107,14 @@ struct acm { struct list_head filled_read_bufs; int write_used; /* number of non-empty write buffers */ int write_ready; /* write urb is not running */ + int old_ready; + int processing; + int transmitting; spinlock_t write_lock; struct mutex mutex; struct usb_cdc_line_coding line; /* bits, stop, parity */ struct work_struct work; /* work queue entry for line discipline waking up */ + struct work_struct waker; struct tasklet_struct urb_task; /* rx processing */ spinlock_t throttle_lock; /* synchronize throtteling and read callback */ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ @@ -123,6 +127,7 @@ struct acm { unsigned char clocal; /* termios CLOCAL */ unsigned int ctrl_caps; /* control capabilities from the class specific header */ unsigned int susp_count; /* number of suspended interfaces */ + struct acm_wb *delayed_wb; /* write queued for a device about to be woken */ }; #define CDC_DATA_INTERFACE_TYPE 0x0a diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 731db051070a..7e8e1235e4e5 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -28,8 +28,9 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.02" +#define DRIVER_VERSION "v0.03" #define DRIVER_AUTHOR "Oliver Neukum" +#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management" static struct usb_device_id wdm_ids[] = { { @@ -87,6 +88,7 @@ struct wdm_device { dma_addr_t ihandle; struct mutex wlock; struct mutex rlock; + struct mutex plock; wait_queue_head_t wait; struct work_struct rxwork; int werr; @@ -205,7 +207,7 @@ static void wdm_int_callback(struct urb *urb) req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; req->wValue = 0; req->wIndex = desc->inum; - req->wLength = cpu_to_le16(desc->bMaxPacketSize0); + req->wLength = cpu_to_le16(desc->wMaxCommand); usb_fill_control_urb( desc->response, @@ -214,7 +216,7 @@ static void wdm_int_callback(struct urb *urb) usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), (unsigned char *)req, desc->inbuf, - desc->bMaxPacketSize0, + desc->wMaxCommand, wdm_in_callback, desc ); @@ -247,6 +249,7 @@ exit: static void kill_urbs(struct wdm_device *desc) { + /* the order here is essential */ usb_kill_urb(desc->command); usb_kill_urb(desc->validity); usb_kill_urb(desc->response); @@ -266,7 +269,7 @@ static void cleanup(struct wdm_device *desc) desc->sbuf, desc->validity->transfer_dma); usb_buffer_free(interface_to_usbdev(desc->intf), - desc->wMaxPacketSize, + desc->wMaxCommand, desc->inbuf, desc->response->transfer_dma); kfree(desc->orq); @@ -299,6 +302,9 @@ static ssize_t wdm_write if (r) goto outnl; + r = usb_autopm_get_interface(desc->intf); + if (r < 0) + goto outnp; r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); if (r < 0) @@ -347,11 +353,14 @@ static ssize_t wdm_write if (rv < 0) { kfree(buf); clear_bit(WDM_IN_USE, &desc->flags); + err("Tx URB error: %d", rv); } else { dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d", req->wIndex); } out: + usb_autopm_put_interface(desc->intf); +outnp: mutex_unlock(&desc->wlock); outnl: return rv < 0 ? rv : count; @@ -376,6 +385,11 @@ retry: rv = wait_event_interruptible(desc->wait, test_bit(WDM_READ, &desc->flags)); + if (test_bit(WDM_DISCONNECTING, &desc->flags)) { + rv = -ENODEV; + goto err; + } + usb_mark_last_busy(interface_to_usbdev(desc->intf)); if (rv < 0) { rv = -ERESTARTSYS; goto err; @@ -418,6 +432,9 @@ retry: desc->ubuf[i] = desc->ubuf[i + cntr]; desc->length -= cntr; + /* in case we had outstanding data */ + if (!desc->length) + clear_bit(WDM_READ, &desc->flags); rv = cntr; err: @@ -480,18 +497,28 @@ static int wdm_open(struct inode *inode, struct file *file) if (test_bit(WDM_DISCONNECTING, &desc->flags)) goto out; - desc->count++; + ; file->private_data = desc; - rv = usb_submit_urb(desc->validity, GFP_KERNEL); - + rv = usb_autopm_get_interface(desc->intf); if (rv < 0) { - desc->count--; - err("Error submitting int urb - %d", rv); + err("Error autopm - %d", rv); goto out; } - rv = 0; + intf->needs_remote_wakeup = 1; + mutex_lock(&desc->plock); + if (!desc->count++) { + rv = usb_submit_urb(desc->validity, GFP_KERNEL); + if (rv < 0) { + desc->count--; + err("Error submitting int urb - %d", rv); + } + } else { + rv = 0; + } + mutex_unlock(&desc->plock); + usb_autopm_put_interface(desc->intf); out: mutex_unlock(&wdm_mutex); return rv; @@ -502,10 +529,15 @@ static int wdm_release(struct inode *inode, struct file *file) struct wdm_device *desc = file->private_data; mutex_lock(&wdm_mutex); + mutex_lock(&desc->plock); desc->count--; + mutex_unlock(&desc->plock); + if (!desc->count) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); kill_urbs(desc); + if (!test_bit(WDM_DISCONNECTING, &desc->flags)) + desc->intf->needs_remote_wakeup = 0; } mutex_unlock(&wdm_mutex); return 0; @@ -597,6 +629,7 @@ next_desc: goto out; mutex_init(&desc->wlock); mutex_init(&desc->rlock); + mutex_init(&desc->plock); spin_lock_init(&desc->iuspin); init_waitqueue_head(&desc->wait); desc->wMaxCommand = maxcom; @@ -698,6 +731,7 @@ static void wdm_disconnect(struct usb_interface *intf) spin_lock_irqsave(&desc->iuspin, flags); set_bit(WDM_DISCONNECTING, &desc->flags); set_bit(WDM_READ, &desc->flags); + /* to terminate pending flushes */ clear_bit(WDM_IN_USE, &desc->flags); spin_unlock_irqrestore(&desc->iuspin, flags); cancel_work_sync(&desc->rxwork); @@ -708,11 +742,81 @@ static void wdm_disconnect(struct usb_interface *intf) mutex_unlock(&wdm_mutex); } +static int wdm_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct wdm_device *desc = usb_get_intfdata(intf); + int rv = 0; + + dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); + + mutex_lock(&desc->plock); +#ifdef CONFIG_PM + if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) { + rv = -EBUSY; + } else { +#endif + cancel_work_sync(&desc->rxwork); + kill_urbs(desc); +#ifdef CONFIG_PM + } +#endif + mutex_unlock(&desc->plock); + + return rv; +} + +static int recover_from_urb_loss(struct wdm_device *desc) +{ + int rv = 0; + + if (desc->count) { + rv = usb_submit_urb(desc->validity, GFP_NOIO); + if (rv < 0) + err("Error resume submitting int urb - %d", rv); + } + return rv; +} +static int wdm_resume(struct usb_interface *intf) +{ + struct wdm_device *desc = usb_get_intfdata(intf); + int rv; + + dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); + mutex_lock(&desc->plock); + rv = recover_from_urb_loss(desc); + mutex_unlock(&desc->plock); + return rv; +} + +static int wdm_pre_reset(struct usb_interface *intf) +{ + struct wdm_device *desc = usb_get_intfdata(intf); + + mutex_lock(&desc->plock); + return 0; +} + +static int wdm_post_reset(struct usb_interface *intf) +{ + struct wdm_device *desc = usb_get_intfdata(intf); + int rv; + + rv = recover_from_urb_loss(desc); + mutex_unlock(&desc->plock); + return 0; +} + static struct usb_driver wdm_driver = { .name = "cdc_wdm", .probe = wdm_probe, .disconnect = wdm_disconnect, + .suspend = wdm_suspend, + .resume = wdm_resume, + .reset_resume = wdm_resume, + .pre_reset = wdm_pre_reset, + .post_reset = wdm_post_reset, .id_table = wdm_ids, + .supports_autosuspend = 1, }; /* --- low level module stuff --- */ @@ -735,6 +839,5 @@ module_init(wdm_init); module_exit(wdm_exit); MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION("USB Abstract Control Model driver for " - "USB WCM Device Management"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 83d9dc379d96..6ec38175a817 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -46,8 +46,6 @@ * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk> * Converted file reading routine to dump to buffer once * per device, not per bus - * - * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $ */ #include <linux/fs.h> @@ -63,8 +61,6 @@ #include "usb.h" #include "hcd.h" -#define MAX_TOPO_LEVEL 6 - /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ #define ALLOW_SERIAL_NUMBER diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 9218cca21043..20290c5b1562 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -19,8 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $ - * * This file implements the usbfs/x/y files, where * x is the bus number and y the device number. * @@ -61,6 +59,22 @@ /* Mutual exclusion for removal, open, and release */ DEFINE_MUTEX(usbfs_mutex); +struct dev_state { + struct list_head list; /* state list */ + struct usb_device *dev; + struct file *file; + spinlock_t lock; /* protects the async urb lists */ + struct list_head async_pending; + struct list_head async_completed; + wait_queue_head_t wait; /* wake up if a request completed */ + unsigned int discsignr; + struct pid *disc_pid; + uid_t disc_uid, disc_euid; + void __user *disccontext; + unsigned long ifclaimed; + u32 secid; +}; + struct async { struct list_head asynclist; struct dev_state *ps; @@ -536,23 +550,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, return ret; } -static int __match_minor(struct device *dev, void *data) +static int match_devt(struct device *dev, void *data) { - int minor = *((int *)data); - - if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) - return 1; - return 0; + return dev->devt == (dev_t) (unsigned long) data; } -static struct usb_device *usbdev_lookup_by_minor(int minor) +static struct usb_device *usbdev_lookup_by_devt(dev_t devt) { struct device *dev; - dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor); + dev = bus_find_device(&usb_bus_type, NULL, + (void *) (unsigned long) devt, match_devt); if (!dev) return NULL; - put_device(dev); return container_of(dev, struct usb_device, dev); } @@ -575,21 +585,27 @@ static int usbdev_open(struct inode *inode, struct file *file) goto out; ret = -ENOENT; + /* usbdev device-node */ if (imajor(inode) == USB_DEVICE_MAJOR) - dev = usbdev_lookup_by_minor(iminor(inode)); + dev = usbdev_lookup_by_devt(inode->i_rdev); #ifdef CONFIG_USB_DEVICEFS /* procfs file */ - if (!dev) + if (!dev) { dev = inode->i_private; + if (dev && dev->usbfs_dentry && + dev->usbfs_dentry->d_inode == inode) + usb_get_dev(dev); + else + dev = NULL; + } #endif - if (!dev) + if (!dev || dev->state == USB_STATE_NOTATTACHED) goto out; ret = usb_autoresume_device(dev); if (ret) goto out; - usb_get_dev(dev); ret = 0; ps->dev = dev; ps->file = file; @@ -609,8 +625,10 @@ static int usbdev_open(struct inode *inode, struct file *file) list_add_tail(&ps->list, &dev->filelist); file->private_data = ps; out: - if (ret) + if (ret) { kfree(ps); + usb_put_dev(dev); + } mutex_unlock(&usbfs_mutex); unlock_kernel(); return ret; @@ -874,7 +892,7 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg) static int proc_resetdevice(struct dev_state *ps) { - return usb_reset_composite_device(ps->dev, NULL); + return usb_reset_device(ps->dev); } static int proc_setintf(struct dev_state *ps, void __user *arg) @@ -1682,25 +1700,49 @@ const struct file_operations usbdev_file_operations = { .release = usbdev_release, }; +void usb_fs_classdev_common_remove(struct usb_device *udev) +{ + struct dev_state *ps; + struct siginfo sinfo; + + while (!list_empty(&udev->filelist)) { + ps = list_entry(udev->filelist.next, struct dev_state, list); + destroy_all_async(ps); + wake_up_all(&ps->wait); + list_del_init(&ps->list); + if (ps->discsignr) { + sinfo.si_signo = ps->discsignr; + sinfo.si_errno = EPIPE; + sinfo.si_code = SI_ASYNCIO; + sinfo.si_addr = ps->disccontext; + kill_pid_info_as_uid(ps->discsignr, &sinfo, + ps->disc_pid, ps->disc_uid, + ps->disc_euid, ps->secid); + } + } +} + #ifdef CONFIG_USB_DEVICE_CLASS static struct class *usb_classdev_class; static int usb_classdev_add(struct usb_device *dev) { - int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - - dev->usb_classdev = device_create(usb_classdev_class, &dev->dev, - MKDEV(USB_DEVICE_MAJOR, minor), - "usbdev%d.%d", dev->bus->busnum, dev->devnum); - if (IS_ERR(dev->usb_classdev)) - return PTR_ERR(dev->usb_classdev); - + struct device *cldev; + + cldev = device_create_drvdata(usb_classdev_class, &dev->dev, + dev->dev.devt, NULL, "usbdev%d.%d", + dev->bus->busnum, dev->devnum); + if (IS_ERR(cldev)) + return PTR_ERR(cldev); + dev->usb_classdev = cldev; return 0; } static void usb_classdev_remove(struct usb_device *dev) { - device_unregister(dev->usb_classdev); + if (dev->usb_classdev) + device_unregister(dev->usb_classdev); + usb_fs_classdev_common_remove(dev); } static int usb_classdev_notify(struct notifier_block *self, @@ -1750,6 +1792,11 @@ int __init usb_devio_init(void) usb_classdev_class = NULL; goto out; } + /* devices of this class shadow the major:minor of their parent + * device, so clear ->dev_kobj to prevent adding duplicate entries + * to /sys/dev + */ + usb_classdev_class->dev_kobj = NULL; usb_register_notify(&usbdev_nb); #endif diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 1e56f1cfa6dc..ddb54e14a5c5 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -201,6 +201,7 @@ static int usb_probe_interface(struct device *dev) intf = to_usb_interface(dev); udev = interface_to_usbdev(intf); + intf->needs_binding = 0; if (udev->authorized == 0) { dev_err(&intf->dev, "Device is not authorized for usage\n"); @@ -257,15 +258,16 @@ static int usb_unbind_interface(struct device *dev) udev = interface_to_usbdev(intf); error = usb_autoresume_device(udev); - /* release all urbs for this interface */ - usb_disable_interface(interface_to_usbdev(intf), intf); + /* Terminate all URBs for this interface unless the driver + * supports "soft" unbinding. + */ + if (!driver->soft_unbind) + usb_disable_interface(udev, intf); driver->disconnect(intf); /* reset other interface state */ - usb_set_interface(interface_to_usbdev(intf), - intf->altsetting[0].desc.bInterfaceNumber, - 0); + usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); usb_set_intfdata(intf, NULL); intf->condition = USB_INTERFACE_UNBOUND; @@ -310,6 +312,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, dev->driver = &driver->drvwrap.driver; usb_set_intfdata(iface, priv); + iface->needs_binding = 0; usb_pm_lock(udev); iface->condition = USB_INTERFACE_BOUND; @@ -586,7 +589,7 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) struct usb_device *usb_dev; /* driver is often null here; dev_dbg() would oops */ - pr_debug("usb %s: uevent\n", dev->bus_id); + pr_debug("usb %s: uevent\n", dev_name(dev)); if (is_usb_device(dev)) usb_dev = to_usb_device(dev); @@ -596,11 +599,11 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) } if (usb_dev->devnum < 0) { - pr_debug("usb %s: already deleted?\n", dev->bus_id); + pr_debug("usb %s: already deleted?\n", dev_name(dev)); return -ENODEV; } if (!usb_dev->bus) { - pr_debug("usb %s: bus removed?\n", dev->bus_id); + pr_debug("usb %s: bus removed?\n", dev_name(dev)); return -ENODEV; } @@ -771,6 +774,104 @@ void usb_deregister(struct usb_driver *driver) } EXPORT_SYMBOL_GPL(usb_deregister); + +/* Forced unbinding of a USB interface driver, either because + * it doesn't support pre_reset/post_reset/reset_resume or + * because it doesn't support suspend/resume. + * + * The caller must hold @intf's device's lock, but not its pm_mutex + * and not @intf->dev.sem. + */ +void usb_forced_unbind_intf(struct usb_interface *intf) +{ + struct usb_driver *driver = to_usb_driver(intf->dev.driver); + + dev_dbg(&intf->dev, "forced unbind\n"); + usb_driver_release_interface(driver, intf); + + /* Mark the interface for later rebinding */ + intf->needs_binding = 1; +} + +/* Delayed forced unbinding of a USB interface driver and scan + * for rebinding. + * + * The caller must hold @intf's device's lock, but not its pm_mutex + * and not @intf->dev.sem. + * + * FIXME: The caller must block system sleep transitions. + */ +void usb_rebind_intf(struct usb_interface *intf) +{ + int rc; + + /* Delayed unbind of an existing driver */ + if (intf->dev.driver) { + struct usb_driver *driver = + to_usb_driver(intf->dev.driver); + + dev_dbg(&intf->dev, "forced unbind\n"); + usb_driver_release_interface(driver, intf); + } + + /* Try to rebind the interface */ + intf->needs_binding = 0; + rc = device_attach(&intf->dev); + if (rc < 0) + dev_warn(&intf->dev, "rebind failed: %d\n", rc); +} + +#define DO_UNBIND 0 +#define DO_REBIND 1 + +/* Unbind drivers for @udev's interfaces that don't support suspend/resume, + * or rebind interfaces that have been unbound, according to @action. + * + * The caller must hold @udev's device lock. + * FIXME: For rebinds, the caller must block system sleep transitions. + */ +static void do_unbind_rebind(struct usb_device *udev, int action) +{ + struct usb_host_config *config; + int i; + struct usb_interface *intf; + struct usb_driver *drv; + + config = udev->actconfig; + if (config) { + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intf = config->interface[i]; + switch (action) { + case DO_UNBIND: + if (intf->dev.driver) { + drv = to_usb_driver(intf->dev.driver); + if (!drv->suspend || !drv->resume) + usb_forced_unbind_intf(intf); + } + break; + case DO_REBIND: + if (intf->needs_binding) { + + /* FIXME: The next line is needed because we are going to probe + * the interface, but as far as the PM core is concerned the + * interface is still suspended. The problem wouldn't exist + * if we could rebind the interface during the interface's own + * resume() call, but at the time the usb_device isn't locked! + * + * The real solution will be to carry this out during the device's + * complete() callback. Until that is implemented, we have to + * use this hack. + */ +// intf->dev.power.sleeping = 0; + + usb_rebind_intf(intf); + } + break; + } + } + } +} + #ifdef CONFIG_PM /* Caller has locked udev's pm_mutex */ @@ -805,8 +906,6 @@ static int usb_resume_device(struct usb_device *udev) if (udev->state == USB_STATE_NOTATTACHED) goto done; - if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume) - goto done; /* Can't resume it if it doesn't have a driver. */ if (udev->dev.driver == NULL) { @@ -842,7 +941,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) goto done; driver = to_usb_driver(intf->dev.driver); - if (driver->suspend && driver->resume) { + if (driver->suspend) { status = driver->suspend(intf, msg); if (status == 0) mark_quiesced(intf); @@ -850,12 +949,10 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) dev_err(&intf->dev, "%s error %d\n", "suspend", status); } else { - /* - * FIXME else if there's no suspend method, disconnect... - * Not possible if auto_pm is set... - */ - dev_warn(&intf->dev, "no suspend for driver %s?\n", - driver->name); + /* Later we will unbind the driver and reprobe */ + intf->needs_binding = 1; + dev_warn(&intf->dev, "no %s for driver %s?\n", + "suspend", driver->name); mark_quiesced(intf); } @@ -879,10 +976,12 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) goto done; /* Can't resume it if it doesn't have a driver. */ - if (intf->condition == USB_INTERFACE_UNBOUND) { - status = -ENOTCONN; + if (intf->condition == USB_INTERFACE_UNBOUND) + goto done; + + /* Don't resume if the interface is marked for rebinding */ + if (intf->needs_binding) goto done; - } driver = to_usb_driver(intf->dev.driver); if (reset_resume) { @@ -892,7 +991,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) dev_err(&intf->dev, "%s error %d\n", "reset_resume", status); } else { - /* status = -EOPNOTSUPP; */ + intf->needs_binding = 1; dev_warn(&intf->dev, "no %s for driver %s?\n", "reset_resume", driver->name); } @@ -903,7 +1002,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) dev_err(&intf->dev, "%s error %d\n", "resume", status); } else { - /* status = -EOPNOTSUPP; */ + intf->needs_binding = 1; dev_warn(&intf->dev, "no %s for driver %s?\n", "resume", driver->name); } @@ -911,11 +1010,10 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) done: dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status); - if (status == 0) + if (status == 0 && intf->condition == USB_INTERFACE_BOUND) mark_active(intf); - /* FIXME: Unbind the driver and reprobe if the resume failed - * (not possible if auto_pm is set) */ + /* Later we will unbind the driver and/or reprobe, if necessary */ return status; } @@ -1173,11 +1271,8 @@ static int usb_resume_both(struct usb_device *udev) * then we're stuck. */ status = usb_resume_device(udev); } - } else { - - /* Needed for reset-resume */ + } else if (udev->reset_resume) status = usb_resume_device(udev); - } if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { @@ -1474,6 +1569,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) { int status; + do_unbind_rebind(udev, DO_UNBIND); usb_pm_lock(udev); udev->auto_pm = 0; status = usb_suspend_both(udev, msg); @@ -1501,6 +1597,7 @@ int usb_external_resume_device(struct usb_device *udev) status = usb_resume_both(udev); udev->last_busy = jiffies; usb_pm_unlock(udev); + do_unbind_rebind(udev, DO_REBIND); /* Now that the device is awake, we can start trying to autosuspend * it again. */ @@ -1542,14 +1639,11 @@ static int usb_resume(struct device *dev) udev = to_usb_device(dev); /* If udev->skip_sys_resume is set then udev was already suspended - * when the system suspend started, so we don't want to resume - * udev during this system wakeup. However a reset-resume counts - * as a wakeup event, so allow a reset-resume to occur if remote - * wakeup is enabled. */ - if (udev->skip_sys_resume) { - if (!(udev->reset_resume && udev->do_remote_wakeup)) - return -EHOSTUNREACH; - } + * when the system sleep started, so we don't want to resume it + * during this system wakeup. + */ + if (udev->skip_sys_resume) + return 0; return usb_external_resume_device(udev); } diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index fae55a31e26d..22912136fc14 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -296,7 +296,7 @@ int usb_create_ep_files(struct device *parent, retval = endpoint_get_minor(ep_dev); if (retval) { dev_err(parent, "can not allocate minor number for %s\n", - ep_dev->dev.bus_id); + dev_name(&ep_dev->dev)); goto error_register; } @@ -307,7 +307,7 @@ int usb_create_ep_files(struct device *parent, ep_dev->dev.class = ep_class->class; ep_dev->dev.parent = parent; ep_dev->dev.release = ep_device_release; - snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x", + dev_set_name(&ep_dev->dev, "usbdev%d.%d_ep%02x", udev->bus->busnum, udev->devnum, endpoint->desc.bEndpointAddress); diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index c6a95395e52a..6b1b229e38cd 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -150,7 +150,7 @@ int usb_register_dev(struct usb_interface *intf, int retval = -EINVAL; int minor_base = class_driver->minor_base; int minor = 0; - char name[BUS_ID_SIZE]; + char name[20]; char *temp; #ifdef CONFIG_USB_DYNAMIC_MINORS @@ -190,14 +190,15 @@ int usb_register_dev(struct usb_interface *intf, intf->minor = minor; /* create a usb class device for this usb interface */ - snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base); + snprintf(name, sizeof(name), class_driver->name, minor - minor_base); temp = strrchr(name, '/'); - if (temp && (temp[1] != 0x00)) + if (temp && (temp[1] != '\0')) ++temp; else temp = name; - intf->usb_dev = device_create(usb_class->class, &intf->dev, - MKDEV(USB_MAJOR, minor), "%s", temp); + intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev, + MKDEV(USB_MAJOR, minor), NULL, + "%s", temp); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); usb_minors[intf->minor] = NULL; @@ -227,7 +228,7 @@ void usb_deregister_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { int minor_base = class_driver->minor_base; - char name[BUS_ID_SIZE]; + char name[20]; #ifdef CONFIG_USB_DYNAMIC_MINORS minor_base = 0; @@ -242,7 +243,7 @@ void usb_deregister_dev(struct usb_interface *intf, usb_minors[intf->minor] = NULL; up_write(&minor_rwsem); - snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); + snprintf(name, sizeof(name), class_driver->name, intf->minor - minor_base); device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); intf->usb_dev = NULL; intf->minor = -1; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 42a436478b78..f7bfd72ef115 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -900,14 +900,14 @@ static int register_root_hub(struct usb_hcd *hcd) if (retval != sizeof usb_dev->descriptor) { mutex_unlock(&usb_bus_list_lock); dev_dbg (parent_dev, "can't read %s device descriptor %d\n", - usb_dev->dev.bus_id, retval); + dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; } retval = usb_new_device (usb_dev); if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", - usb_dev->dev.bus_id, retval); + dev_name(&usb_dev->dev), retval); } mutex_unlock(&usb_bus_list_lock); @@ -1764,7 +1764,7 @@ EXPORT_SYMBOL_GPL (usb_hc_died); * If memory is unavailable, returns NULL. */ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, - struct device *dev, char *bus_name) + struct device *dev, const char *bus_name) { struct usb_hcd *hcd; diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index b9de1569b39e..5b0b59b0d89b 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -21,6 +21,8 @@ #include <linux/rwsem.h> +#define MAX_TOPO_LEVEL 6 + /* This file contains declarations of usbcore internals that are mostly * used or exposed by Host Controller Drivers. */ @@ -235,7 +237,7 @@ extern void usb_hcd_disable_endpoint(struct usb_device *udev, extern int usb_hcd_get_frame_number(struct usb_device *udev); extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, - struct device *dev, char *bus_name); + struct device *dev, const char *bus_name); extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd); extern void usb_put_hcd(struct usb_hcd *hcd); extern int usb_add_hcd(struct usb_hcd *hcd, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4cfe32a16c37..107e1d25ddec 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -72,7 +72,6 @@ struct usb_hub { unsigned limited_power:1; unsigned quiescing:1; - unsigned activating:1; unsigned disconnected:1; unsigned has_indicators:1; @@ -131,6 +130,12 @@ MODULE_PARM_DESC(use_both_schemes, DECLARE_RWSEM(ehci_cf_port_reset_rwsem); EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); +#define HUB_DEBOUNCE_TIMEOUT 1500 +#define HUB_DEBOUNCE_STEP 25 +#define HUB_DEBOUNCE_STABLE 100 + + +static int usb_reset_and_verify_device(struct usb_device *udev); static inline char *portspeed(int portstatus) { @@ -535,37 +540,6 @@ static void hub_power_on(struct usb_hub *hub) msleep(max(pgood_delay, (unsigned) 100)); } -static void hub_quiesce(struct usb_hub *hub) -{ - /* (nonblocking) khubd and related activity won't re-trigger */ - hub->quiescing = 1; - hub->activating = 0; - - /* (blocking) stop khubd and related activity */ - usb_kill_urb(hub->urb); - if (hub->has_indicators) - cancel_delayed_work_sync(&hub->leds); - if (hub->tt.hub) - cancel_work_sync(&hub->tt.kevent); -} - -static void hub_activate(struct usb_hub *hub) -{ - int status; - - hub->quiescing = 0; - hub->activating = 1; - - status = usb_submit_urb(hub->urb, GFP_NOIO); - if (status < 0) - dev_err(hub->intfdev, "activate --> %d\n", status); - if (hub->has_indicators && blinkenlights) - schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); - - /* scan all ports ASAP */ - kick_khubd(hub); -} - static int hub_hub_status(struct usb_hub *hub, u16 *status, u16 *change) { @@ -624,136 +598,149 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) kick_khubd(hub); } -/* caller has locked the hub device */ -static void hub_stop(struct usb_hub *hub) +enum hub_activation_type { + HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME +}; + +static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) { struct usb_device *hdev = hub->hdev; - int i; + int port1; + int status; + bool need_debounce_delay = false; - /* Disconnect all the children */ - for (i = 0; i < hdev->maxchild; ++i) { - if (hdev->children[i]) - usb_disconnect(&hdev->children[i]); - } - hub_quiesce(hub); -} + /* After a resume, port power should still be on. + * For any other type of activation, turn it on. + */ + if (type != HUB_RESUME) + hub_power_on(hub); -#define HUB_RESET 1 -#define HUB_RESUME 2 -#define HUB_RESET_RESUME 3 + /* Check each port and set hub->change_bits to let khubd know + * which ports need attention. + */ + for (port1 = 1; port1 <= hdev->maxchild; ++port1) { + struct usb_device *udev = hdev->children[port1-1]; + u16 portstatus, portchange; -#ifdef CONFIG_PM + portstatus = portchange = 0; + status = hub_port_status(hub, port1, &portstatus, &portchange); + if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) + dev_dbg(hub->intfdev, + "port %d: status %04x change %04x\n", + port1, portstatus, portchange); -/* Try to identify which devices need USB-PERSIST handling */ -static int persistent_device(struct usb_device *udev) -{ - int i; - int retval; - struct usb_host_config *actconfig; + /* After anything other than HUB_RESUME (i.e., initialization + * or any sort of reset), every port should be disabled. + * Unconnected ports should likewise be disabled (paranoia), + * and so should ports for which we have no usb_device. + */ + if ((portstatus & USB_PORT_STAT_ENABLE) && ( + type != HUB_RESUME || + !(portstatus & USB_PORT_STAT_CONNECTION) || + !udev || + udev->state == USB_STATE_NOTATTACHED)) { + clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); + portstatus &= ~USB_PORT_STAT_ENABLE; + } - /* Explicitly not marked persistent? */ - if (!udev->persist_enabled) - return 0; + /* Clear status-change flags; we'll debounce later */ + if (portchange & USB_PORT_STAT_C_CONNECTION) { + need_debounce_delay = true; + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + } + if (portchange & USB_PORT_STAT_C_ENABLE) { + need_debounce_delay = true; + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_ENABLE); + } - /* No active config? */ - actconfig = udev->actconfig; - if (!actconfig) - return 0; + if (!udev || udev->state == USB_STATE_NOTATTACHED) { + /* Tell khubd to disconnect the device or + * check for a new connection + */ + if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) + set_bit(port1, hub->change_bits); + + } else if (portstatus & USB_PORT_STAT_ENABLE) { + /* The power session apparently survived the resume. + * If there was an overcurrent or suspend change + * (i.e., remote wakeup request), have khubd + * take care of it. + */ + if (portchange) + set_bit(port1, hub->change_bits); - /* FIXME! We should check whether it's open here or not! */ + } else if (udev->persist_enabled) { +#ifdef CONFIG_PM + udev->reset_resume = 1; +#endif + set_bit(port1, hub->change_bits); - /* - * Check that all the interface drivers have a - * 'reset_resume' entrypoint + } else { + /* The power session is gone; tell khubd */ + usb_set_device_state(udev, USB_STATE_NOTATTACHED); + set_bit(port1, hub->change_bits); + } + } + + /* If no port-status-change flags were set, we don't need any + * debouncing. If flags were set we can try to debounce the + * ports all at once right now, instead of letting khubd do them + * one at a time later on. + * + * If any port-status changes do occur during this delay, khubd + * will see them later and handle them normally. */ - retval = 0; - for (i = 0; i < actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf; - struct usb_driver *driver; + if (need_debounce_delay) + msleep(HUB_DEBOUNCE_STABLE); - intf = actconfig->interface[i]; - if (!intf->dev.driver) - continue; - driver = to_usb_driver(intf->dev.driver); - if (!driver->reset_resume) - return 0; - /* - * We have at least one driver, and that one - * has a reset_resume method. - */ - retval = 1; - } - return retval; -} + hub->quiescing = 0; -static void hub_restart(struct usb_hub *hub, int type) -{ - struct usb_device *hdev = hub->hdev; - int port1; + status = usb_submit_urb(hub->urb, GFP_NOIO); + if (status < 0) + dev_err(hub->intfdev, "activate --> %d\n", status); + if (hub->has_indicators && blinkenlights) + schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); - /* Check each of the children to see if they require - * USB-PERSIST handling or disconnection. Also check - * each unoccupied port to make sure it is still disabled. - */ - for (port1 = 1; port1 <= hdev->maxchild; ++port1) { - struct usb_device *udev = hdev->children[port1-1]; - int status = 0; - u16 portstatus, portchange; + /* Scan all ports that need attention */ + kick_khubd(hub); +} - if (!udev || udev->state == USB_STATE_NOTATTACHED) { - if (type != HUB_RESET) { - status = hub_port_status(hub, port1, - &portstatus, &portchange); - if (status == 0 && (portstatus & - USB_PORT_STAT_ENABLE)) - clear_port_feature(hdev, port1, - USB_PORT_FEAT_ENABLE); - } - continue; - } +enum hub_quiescing_type { + HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND +}; - /* Was the power session lost while we were suspended? */ - status = hub_port_status(hub, port1, &portstatus, &portchange); +static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) +{ + struct usb_device *hdev = hub->hdev; + int i; - /* If the device is gone, khubd will handle it later */ - if (status == 0 && !(portstatus & USB_PORT_STAT_CONNECTION)) - continue; + /* khubd and related activity won't re-trigger */ + hub->quiescing = 1; - /* For "USB_PERSIST"-enabled children we must - * mark the child device for reset-resume and - * turn off the various status changes to prevent - * khubd from disconnecting it later. - */ - if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) && - persistent_device(udev)) { - if (portchange & USB_PORT_STAT_C_ENABLE) - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_ENABLE); - if (portchange & USB_PORT_STAT_C_CONNECTION) - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_CONNECTION); - udev->reset_resume = 1; + if (type != HUB_SUSPEND) { + /* Disconnect all the children */ + for (i = 0; i < hdev->maxchild; ++i) { + if (hdev->children[i]) + usb_disconnect(&hdev->children[i]); } - - /* Otherwise for a reset_resume we must disconnect the child, - * but as we may not lock the child device here - * we have to do a "logical" disconnect. - */ - else if (type == HUB_RESET_RESUME) - hub_port_logical_disconnect(hub, port1); } - hub_activate(hub); + /* Stop khubd and related activity */ + usb_kill_urb(hub->urb); + if (hub->has_indicators) + cancel_delayed_work_sync(&hub->leds); + if (hub->tt.hub) + cancel_work_sync(&hub->tt.kevent); } -#endif /* CONFIG_PM */ - /* caller has locked the hub device */ static int hub_pre_reset(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata(intf); - hub_stop(hub); + hub_quiesce(hub, HUB_PRE_RESET); return 0; } @@ -762,8 +749,7 @@ static int hub_post_reset(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata(intf); - hub_power_on(hub); - hub_activate(hub); + hub_activate(hub, HUB_POST_RESET); return 0; } @@ -1009,8 +995,7 @@ static int hub_configure(struct usb_hub *hub, if (hub->has_indicators && blinkenlights) hub->indicator [0] = INDICATOR_CYCLE; - hub_power_on(hub); - hub_activate(hub); + hub_activate(hub, HUB_INIT); return 0; fail: @@ -1042,7 +1027,7 @@ static void hub_disconnect(struct usb_interface *intf) /* Disconnect all children and quiesce the hub */ hub->error = 0; - hub_stop(hub); + hub_quiesce(hub, HUB_DISCONNECT); usb_set_intfdata (intf, NULL); @@ -1068,6 +1053,12 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); + if (hdev->level == MAX_TOPO_LEVEL) { + dev_err(&intf->dev, "Unsupported bus topology: " + "hub nested too deep\n"); + return -E2BIG; + } + #ifdef CONFIG_USB_OTG_BLACKLIST_HUB if (hdev->parent) { dev_warn(&intf->dev, "ignoring external hub\n"); @@ -1814,6 +1805,51 @@ static int hub_port_reset(struct usb_hub *hub, int port1, #ifdef CONFIG_PM +#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \ + USB_PORT_STAT_SUSPEND) +#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION) + +/* Determine whether the device on a port is ready for a normal resume, + * is ready for a reset-resume, or should be disconnected. + */ +static int check_port_resume_type(struct usb_device *udev, + struct usb_hub *hub, int port1, + int status, unsigned portchange, unsigned portstatus) +{ + /* Is the device still present? */ + if (status || (portstatus & MASK_BITS) != WANT_BITS) { + if (status >= 0) + status = -ENODEV; + } + + /* Can't do a normal resume if the port isn't enabled, + * so try a reset-resume instead. + */ + else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) { + if (udev->persist_enabled) + udev->reset_resume = 1; + else + status = -ENODEV; + } + + if (status) { + dev_dbg(hub->intfdev, + "port %d status %04x.%04x after resume, %d\n", + port1, portchange, portstatus, status); + } else if (udev->reset_resume) { + + /* Late port handoff can set status-change bits */ + if (portchange & USB_PORT_STAT_C_CONNECTION) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + if (portchange & USB_PORT_STAT_C_ENABLE) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_ENABLE); + } + + return status; +} + #ifdef CONFIG_USB_SUSPEND /* @@ -1943,7 +1979,8 @@ static int finish_port_resume(struct usb_device *udev) * resumed. */ if (udev->reset_resume) - status = usb_reset_device(udev); + retry_reset_resume: + status = usb_reset_and_verify_device(udev); /* 10.5.4.5 says be sure devices in the tree are still there. * For now let's assume the device didn't go crazy on resume, @@ -1954,6 +1991,13 @@ static int finish_port_resume(struct usb_device *udev) status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); if (status >= 0) status = (status > 0 ? 0 : -ENODEV); + + /* If a normal resume failed, try doing a reset-resume */ + if (status && !udev->reset_resume && udev->persist_enabled) { + dev_dbg(&udev->dev, "retry with reset-resume\n"); + udev->reset_resume = 1; + goto retry_reset_resume; + } } if (status) { @@ -2002,7 +2046,7 @@ static int finish_port_resume(struct usb_device *udev) * to it will be lost. Using the USB_PERSIST facility, the device can be * made to appear as if it had not disconnected. * - * This facility can be dangerous. Although usb_reset_device() makes + * This facility can be dangerous. Although usb_reset_and_verify_device() makes * every effort to insure that the same device is present after the * reset as before, it cannot provide a 100% guarantee. Furthermore it's * quite possible for a device to remain unaltered but its media to be @@ -2018,7 +2062,6 @@ int usb_port_resume(struct usb_device *udev) int port1 = udev->portnum; int status; u16 portchange, portstatus; - unsigned mask_flags, want_flags; /* Skip the initial Clear-Suspend step for a remote wakeup */ status = hub_port_status(hub, port1, &portstatus, &portchange); @@ -2047,35 +2090,23 @@ int usb_port_resume(struct usb_device *udev) */ status = hub_port_status(hub, port1, &portstatus, &portchange); - SuspendCleared: - if (udev->reset_resume) - want_flags = USB_PORT_STAT_POWER - | USB_PORT_STAT_CONNECTION; - else - want_flags = USB_PORT_STAT_POWER - | USB_PORT_STAT_CONNECTION - | USB_PORT_STAT_ENABLE; - mask_flags = want_flags | USB_PORT_STAT_SUSPEND; + /* TRSMRCY = 10 msec */ + msleep(10); + } - if (status < 0 || (portstatus & mask_flags) != want_flags) { - dev_dbg(hub->intfdev, - "port %d status %04x.%04x after resume, %d\n", - port1, portchange, portstatus, status); - if (status >= 0) - status = -ENODEV; - } else { - if (portchange & USB_PORT_STAT_C_SUSPEND) - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_SUSPEND); - /* TRSMRCY = 10 msec */ - msleep(10); - } + SuspendCleared: + if (status == 0) { + if (portchange & USB_PORT_STAT_C_SUSPEND) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_SUSPEND); } clear_bit(port1, hub->busy_bits); if (!hub->hdev->parent && !hub->busy_bits[0]) usb_enable_root_hub_irq(hub->hdev->bus); + status = check_port_resume_type(udev, + hub, port1, status, portchange, portstatus); if (status == 0) status = finish_port_resume(udev); if (status < 0) { @@ -2085,17 +2116,16 @@ int usb_port_resume(struct usb_device *udev) return status; } +/* caller has locked udev */ static int remote_wakeup(struct usb_device *udev) { int status = 0; - usb_lock_device(udev); if (udev->state == USB_STATE_SUSPENDED) { dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); usb_mark_last_busy(udev); status = usb_external_resume_device(udev); } - usb_unlock_device(udev); return status; } @@ -2108,14 +2138,25 @@ int usb_port_suspend(struct usb_device *udev) return 0; } +/* However we may need to do a reset-resume */ + int usb_port_resume(struct usb_device *udev) { - int status = 0; + struct usb_hub *hub = hdev_to_hub(udev->parent); + int port1 = udev->portnum; + int status; + u16 portchange, portstatus; - /* However we may need to do a reset-resume */ - if (udev->reset_resume) { + status = hub_port_status(hub, port1, &portstatus, &portchange); + status = check_port_resume_type(udev, + hub, port1, status, portchange, portstatus); + + if (status) { + dev_dbg(&udev->dev, "can't resume, status %d\n", status); + hub_port_logical_disconnect(hub, port1); + } else if (udev->reset_resume) { dev_dbg(&udev->dev, "reset-resume\n"); - status = usb_reset_device(udev); + status = usb_reset_and_verify_device(udev); } return status; } @@ -2149,7 +2190,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) dev_dbg(&intf->dev, "%s\n", __func__); /* stop khubd and related activity */ - hub_quiesce(hub); + hub_quiesce(hub, HUB_SUSPEND); return 0; } @@ -2158,7 +2199,7 @@ static int hub_resume(struct usb_interface *intf) struct usb_hub *hub = usb_get_intfdata(intf); dev_dbg(&intf->dev, "%s\n", __func__); - hub_restart(hub, HUB_RESUME); + hub_activate(hub, HUB_RESUME); return 0; } @@ -2167,8 +2208,7 @@ static int hub_reset_resume(struct usb_interface *intf) struct usb_hub *hub = usb_get_intfdata(intf); dev_dbg(&intf->dev, "%s\n", __func__); - hub_power_on(hub); - hub_restart(hub, HUB_RESET_RESUME); + hub_activate(hub, HUB_RESET_RESUME); return 0; } @@ -2218,11 +2258,6 @@ static inline int remote_wakeup(struct usb_device *udev) * every 25ms for transient disconnects. When the port status has been * unchanged for 100ms it returns the port status. */ - -#define HUB_DEBOUNCE_TIMEOUT 1500 -#define HUB_DEBOUNCE_STEP 25 -#define HUB_DEBOUNCE_STABLE 100 - static int hub_port_debounce(struct usb_hub *hub, int port1) { int ret; @@ -2302,7 +2337,7 @@ static int hub_set_address(struct usb_device *udev, int devnum) * Returns device in USB_STATE_ADDRESS, except on error. * * If this is called for an already-existing device (as part of - * usb_reset_device), the caller must own the device lock. For a + * usb_reset_and_verify_device), the caller must own the device lock. For a * newly detected device that is not accessible through any global * pointers, it's not necessary to lock the device. */ @@ -2619,7 +2654,7 @@ hub_power_remaining (struct usb_hub *hub) * This routine is called when: * a port connection-change occurs; * a port enable-change occurs (often caused by EMI); - * usb_reset_device() encounters changed descriptors (as from + * usb_reset_and_verify_device() encounters changed descriptors (as from * a firmware download) * caller already locked the hub */ @@ -2629,9 +2664,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, struct usb_device *hdev = hub->hdev; struct device *hub_dev = hub->intfdev; struct usb_hcd *hcd = bus_to_hcd(hdev->bus); - u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); + unsigned wHubCharacteristics = + le16_to_cpu(hub->descriptor->wHubCharacteristics); + struct usb_device *udev; int status, i; - + dev_dbg (hub_dev, "port %d, status %04x, change %04x, %s\n", port1, portstatus, portchange, portspeed (portstatus)); @@ -2640,30 +2677,73 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, set_port_led(hub, port1, HUB_LED_AUTO); hub->indicator[port1-1] = INDICATOR_AUTO; } - - /* Disconnect any existing devices under this port */ - if (hdev->children[port1-1]) - usb_disconnect(&hdev->children[port1-1]); - clear_bit(port1, hub->change_bits); #ifdef CONFIG_USB_OTG /* during HNP, don't repeat the debounce */ if (hdev->bus->is_b_host) - portchange &= ~USB_PORT_STAT_C_CONNECTION; + portchange &= ~(USB_PORT_STAT_C_CONNECTION | + USB_PORT_STAT_C_ENABLE); #endif - if (portchange & USB_PORT_STAT_C_CONNECTION) { + /* Try to use the debounce delay for protection against + * port-enable changes caused, for example, by EMI. + */ + if (portchange & (USB_PORT_STAT_C_CONNECTION | + USB_PORT_STAT_C_ENABLE)) { status = hub_port_debounce(hub, port1); if (status < 0) { if (printk_ratelimit()) dev_err (hub_dev, "connect-debounce failed, " "port %d disabled\n", port1); - goto done; + portstatus &= ~USB_PORT_STAT_CONNECTION; + } else { + portstatus = status; + } + } + + /* Try to resuscitate an existing device */ + udev = hdev->children[port1-1]; + if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && + udev->state != USB_STATE_NOTATTACHED) { + + usb_lock_device(udev); + if (portstatus & USB_PORT_STAT_ENABLE) { + status = 0; /* Nothing to do */ + } else if (!udev->persist_enabled) { + status = -ENODEV; /* Mustn't resuscitate */ + +#ifdef CONFIG_USB_SUSPEND + } else if (udev->state == USB_STATE_SUSPENDED) { + /* For a suspended device, treat this as a + * remote wakeup event. + */ + if (udev->do_remote_wakeup) + status = remote_wakeup(udev); + + /* Otherwise leave it be; devices can't tell the + * difference between suspended and disabled. + */ + else + status = 0; +#endif + + } else { + status = usb_reset_device(udev); + } + usb_unlock_device(udev); + + if (status == 0) { + clear_bit(port1, hub->change_bits); + return; } - portstatus = status; } - /* Return now if nothing is connected */ + /* Disconnect any existing devices under this port */ + if (udev) + usb_disconnect(&hdev->children[port1-1]); + clear_bit(port1, hub->change_bits); + + /* Return now if debouncing failed or nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { /* maybe switch power back on (e.g. root hub was reset) */ @@ -2677,7 +2757,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, } for (i = 0; i < SET_CONFIG_TRIES; i++) { - struct usb_device *udev; /* reallocate for each attempt, since references * to the previous one can escape in various ways @@ -2858,7 +2937,7 @@ static void hub_events(void) /* If the hub has died, clean up after it */ if (hdev->state == USB_STATE_NOTATTACHED) { hub->error = -ENODEV; - hub_stop(hub); + hub_quiesce(hub, HUB_DISCONNECT); goto loop; } @@ -2877,7 +2956,7 @@ static void hub_events(void) dev_dbg (hub_dev, "resetting for error %d\n", hub->error); - ret = usb_reset_composite_device(hdev, intf); + ret = usb_reset_device(hdev); if (ret) { dev_dbg (hub_dev, "error resetting hub: %d\n", ret); @@ -2894,7 +2973,7 @@ static void hub_events(void) continue; connect_change = test_bit(i, hub->change_bits); if (!test_and_clear_bit(i, hub->event_bits) && - !connect_change && !hub->activating) + !connect_change) continue; ret = hub_port_status(hub, i, @@ -2902,11 +2981,6 @@ static void hub_events(void) if (ret < 0) continue; - if (hub->activating && !hdev->children[i-1] && - (portstatus & - USB_PORT_STAT_CONNECTION)) - connect_change = 1; - if (portchange & USB_PORT_STAT_C_CONNECTION) { clear_port_feature(hdev, i, USB_PORT_FEAT_C_CONNECTION); @@ -2941,11 +3015,16 @@ static void hub_events(void) } if (portchange & USB_PORT_STAT_C_SUSPEND) { + struct usb_device *udev; + clear_port_feature(hdev, i, USB_PORT_FEAT_C_SUSPEND); - if (hdev->children[i-1]) { + udev = hdev->children[i-1]; + if (udev) { + usb_lock_device(udev); ret = remote_wakeup(hdev-> children[i-1]); + usb_unlock_device(udev); if (ret < 0) connect_change = 1; } else { @@ -3002,8 +3081,6 @@ static void hub_events(void) } } - hub->activating = 0; - /* If this is a root hub, tell the HCD it's okay to * re-enable port-change interrupts now. */ if (!hdev->parent && !hub->busy_bits[0]) @@ -3172,12 +3249,12 @@ static int descriptors_changed(struct usb_device *udev, } /** - * usb_reset_device - perform a USB port reset to reinitialize a device + * usb_reset_and_verify_device - perform a USB port reset to reinitialize a device * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) * * WARNING - don't use this routine to reset a composite device * (one with multiple interfaces owned by separate drivers)! - * Use usb_reset_composite_device() instead. + * Use usb_reset_device() instead. * * Do a port reset, reassign the device's address, and establish its * former operating configuration. If the reset fails, or the device's @@ -3201,7 +3278,7 @@ static int descriptors_changed(struct usb_device *udev, * holding the device lock because these tasks should always call * usb_autopm_resume_device(), thereby preventing any unwanted autoresume. */ -int usb_reset_device(struct usb_device *udev) +static int usb_reset_and_verify_device(struct usb_device *udev) { struct usb_device *parent_hdev = udev->parent; struct usb_hub *parent_hub; @@ -3289,26 +3366,28 @@ re_enumerate: hub_port_logical_disconnect(parent_hub, port1); return -ENODEV; } -EXPORT_SYMBOL_GPL(usb_reset_device); /** - * usb_reset_composite_device - warn interface drivers and perform a USB port reset + * usb_reset_device - warn interface drivers and perform a USB port reset * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) - * @iface: interface bound to the driver making the request (optional) * * Warns all drivers bound to registered interfaces (using their pre_reset * method), performs the port reset, and then lets the drivers know that * the reset is over (using their post_reset method). * - * Return value is the same as for usb_reset_device(). + * Return value is the same as for usb_reset_and_verify_device(). * * The caller must own the device lock. For example, it's safe to use * this from a driver probe() routine after downloading new firmware. * For calls that might not occur during probe(), drivers should lock * the device using usb_lock_device_for_reset(). + * + * If an interface is currently being probed or disconnected, we assume + * its driver knows how to handle resets. For all other interfaces, + * if the driver doesn't have pre_reset and post_reset methods then + * we attempt to unbind it and rebind afterward. */ -int usb_reset_composite_device(struct usb_device *udev, - struct usb_interface *iface) +int usb_reset_device(struct usb_device *udev) { int ret; int i; @@ -3324,40 +3403,47 @@ int usb_reset_composite_device(struct usb_device *udev, /* Prevent autosuspend during the reset */ usb_autoresume_device(udev); - if (iface && iface->condition != USB_INTERFACE_BINDING) - iface = NULL; - if (config) { for (i = 0; i < config->desc.bNumInterfaces; ++i) { struct usb_interface *cintf = config->interface[i]; struct usb_driver *drv; + int unbind = 0; if (cintf->dev.driver) { drv = to_usb_driver(cintf->dev.driver); - if (drv->pre_reset) - (drv->pre_reset)(cintf); - /* FIXME: Unbind if pre_reset returns an error or isn't defined */ + if (drv->pre_reset && drv->post_reset) + unbind = (drv->pre_reset)(cintf); + else if (cintf->condition == + USB_INTERFACE_BOUND) + unbind = 1; + if (unbind) + usb_forced_unbind_intf(cintf); } } } - ret = usb_reset_device(udev); + ret = usb_reset_and_verify_device(udev); if (config) { for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { struct usb_interface *cintf = config->interface[i]; struct usb_driver *drv; + int rebind = cintf->needs_binding; - if (cintf->dev.driver) { + if (!rebind && cintf->dev.driver) { drv = to_usb_driver(cintf->dev.driver); if (drv->post_reset) - (drv->post_reset)(cintf); - /* FIXME: Unbind if post_reset returns an error or isn't defined */ + rebind = (drv->post_reset)(cintf); + else if (cintf->condition == + USB_INTERFACE_BOUND) + rebind = 1; } + if (rebind) + usb_rebind_intf(cintf); } } usb_autosuspend_device(udev); return ret; } -EXPORT_SYMBOL_GPL(usb_reset_composite_device); +EXPORT_SYMBOL_GPL(usb_reset_device); diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 1d253dd4ea81..db410e92c80d 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -712,25 +712,11 @@ static void usbfs_add_device(struct usb_device *dev) static void usbfs_remove_device(struct usb_device *dev) { - struct dev_state *ds; - struct siginfo sinfo; - if (dev->usbfs_dentry) { fs_remove_file (dev->usbfs_dentry); dev->usbfs_dentry = NULL; } - while (!list_empty(&dev->filelist)) { - ds = list_entry(dev->filelist.next, struct dev_state, list); - wake_up_all(&ds->wait); - list_del_init(&ds->list); - if (ds->discsignr) { - sinfo.si_signo = ds->discsignr; - sinfo.si_errno = EPIPE; - sinfo.si_code = SI_ASYNCIO; - sinfo.si_addr = ds->disccontext; - kill_pid_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid, ds->secid); - } - } + usb_fs_classdev_common_remove(dev); } static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fe47d145255a..2fcc06eb5e60 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -400,7 +400,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, if (usb_pipein(pipe)) urb_flags |= URB_SHORT_NOT_OK; - for (i = 0; i < io->entries; i++) { + for_each_sg(sg, sg, io->entries, i) { unsigned len; io->urbs[i] = usb_alloc_urb(0, mem_flags); @@ -434,17 +434,17 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, * to prevent stale pointers and to help spot bugs. */ if (dma) { - io->urbs[i]->transfer_dma = sg_dma_address(sg + i); - len = sg_dma_len(sg + i); + io->urbs[i]->transfer_dma = sg_dma_address(sg); + len = sg_dma_len(sg); #if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU) io->urbs[i]->transfer_buffer = NULL; #else - io->urbs[i]->transfer_buffer = sg_virt(&sg[i]); + io->urbs[i]->transfer_buffer = sg_virt(sg); #endif } else { /* hc may use _only_ transfer_buffer */ - io->urbs[i]->transfer_buffer = sg_virt(&sg[i]); - len = sg[i].length; + io->urbs[i]->transfer_buffer = sg_virt(sg); + len = sg->length; } if (length) { @@ -1090,7 +1090,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) if (!device_is_registered(&interface->dev)) continue; dev_dbg(&dev->dev, "unregistering interface %s\n", - interface->dev.bus_id); + dev_name(&interface->dev)); device_del(&interface->dev); usb_remove_sysfs_intf_files(interface); } @@ -1476,7 +1476,7 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev, * * This call is synchronous. The calling context must be able to sleep, * must own the device lock, and must not hold the driver model's USB - * bus mutex; usb device driver probe() methods cannot use this routine. + * bus mutex; usb interface driver probe() methods cannot use this routine. * * Returns zero on success, or else the status code returned by the * underlying call that failed. On successful completion, each interface @@ -1611,7 +1611,7 @@ free_interfaces: intf->dev.dma_mask = dev->dev.dma_mask; device_initialize(&intf->dev); mark_quiesced(intf); - sprintf(&intf->dev.bus_id[0], "%d-%s:%d.%d", + dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum, dev->devpath, configuration, alt->desc.bInterfaceNumber); } @@ -1631,12 +1631,12 @@ free_interfaces: dev_dbg(&dev->dev, "adding %s (config #%d, interface %d)\n", - intf->dev.bus_id, configuration, + dev_name(&intf->dev), configuration, intf->cur_altsetting->desc.bInterfaceNumber); ret = device_add(&intf->dev); if (ret != 0) { dev_err(&dev->dev, "device_add(%s) --> %d\n", - intf->dev.bus_id, ret); + dev_name(&intf->dev), ret); continue; } usb_create_sysfs_intf_files(intf); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 325774375837..84fcaa6a21ec 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -308,7 +308,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, * by location for diagnostics, tools, driver model, etc. The * string is a path along hub ports, from the root. Each device's * dev->devpath will be stable until USB is re-cabled, and hubs - * are often labeled with these port numbers. The bus_id isn't + * are often labeled with these port numbers. The name isn't * as stable: bus->busnum changes easily from modprobe order, * cardbus or pci hotplugging, and so on. */ @@ -316,7 +316,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, dev->devpath[0] = '0'; dev->dev.parent = bus->controller; - sprintf(&dev->dev.bus_id[0], "usb%d", bus->busnum); + dev_set_name(&dev->dev, "usb%d", bus->busnum); root_hub = 1; } else { /* match any labeling on the hubs; it's one-based */ @@ -328,8 +328,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, "%s.%d", parent->devpath, port1); dev->dev.parent = &parent->dev; - sprintf(&dev->dev.bus_id[0], "%d-%s", - bus->busnum, dev->devpath); + dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath); /* hub driver sets up TT records */ } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 1a8bc21c335e..d9a6e16dbf84 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -29,6 +29,8 @@ extern int usb_choose_configuration(struct usb_device *udev); extern void usb_kick_khubd(struct usb_device *dev); extern int usb_match_device(struct usb_device *dev, const struct usb_device_id *id); +extern void usb_forced_unbind_intf(struct usb_interface *intf); +extern void usb_rebind_intf(struct usb_interface *intf); extern int usb_hub_init(void); extern void usb_hub_cleanup(void); @@ -140,26 +142,11 @@ extern struct usb_driver usbfs_driver; extern const struct file_operations usbfs_devices_fops; extern const struct file_operations usbdev_file_operations; extern void usbfs_conn_disc_event(void); +extern void usb_fs_classdev_common_remove(struct usb_device *udev); extern int usb_devio_init(void); extern void usb_devio_cleanup(void); -struct dev_state { - struct list_head list; /* state list */ - struct usb_device *dev; - struct file *file; - spinlock_t lock; /* protects the async urb lists */ - struct list_head async_pending; - struct list_head async_completed; - wait_queue_head_t wait; /* wake up if a request completed */ - unsigned int discsignr; - struct pid *disc_pid; - uid_t disc_uid, disc_euid; - void __user *disccontext; - unsigned long ifclaimed; - u32 secid; -}; - /* internal notify stuff */ extern void usb_notify_add_device(struct usb_device *udev); extern void usb_notify_remove_device(struct usb_device *udev); diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index d6bab0d5f453..c6a8c6b1116a 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -586,6 +586,20 @@ config USB_G_PRINTER For more information, see Documentation/usb/gadget_printer.txt which includes sample code for accessing the device file. +config USB_CDC_COMPOSITE + tristate "CDC Composite Device (Ethernet and ACM)" + depends on NET + help + This driver provides two functions in one configuration: + a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link. + + This driver requires four bulk and two interrupt endpoints, + plus the ability to handle altsettings. Not all peripheral + controllers are that capable. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module. + # put drivers that need isochronous transfer support (for audio # or video class gadget drivers), or specific hardware, here. diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index e258afd25faf..fcb5cb9094d9 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -22,18 +22,22 @@ obj-$(CONFIG_USB_M66592) += m66592-udc.o # # USB gadget drivers # -g_zero-objs := zero.o usbstring.o config.o epautoconf.o -g_ether-objs := ether.o usbstring.o config.o epautoconf.o -g_serial-objs := serial.o usbstring.o config.o epautoconf.o +C_UTILS = composite.o usbstring.o config.o epautoconf.o + +g_zero-objs := zero.o f_sourcesink.o f_loopback.o $(C_UTILS) +g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS) +g_serial-objs := serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS) g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o gadgetfs-objs := inode.o g_file_storage-objs := file_storage.o usbstring.o config.o \ epautoconf.o g_printer-objs := printer.o usbstring.o config.o \ epautoconf.o +g_cdc-objs := cdc2.o u_ether.o f_ecm.o \ + u_serial.o f_acm.o $(C_UTILS) ifeq ($(CONFIG_USB_ETH_RNDIS),y) - g_ether-objs += rndis.o + g_ether-objs += f_rndis.o rndis.o endif obj-$(CONFIG_USB_ZERO) += g_zero.o @@ -43,4 +47,5 @@ obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o obj-$(CONFIG_USB_G_SERIAL) += g_serial.o obj-$(CONFIG_USB_G_PRINTER) += g_printer.o obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o +obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index f261d2a9a5f0..1500e1b3c302 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3342,7 +3342,7 @@ static int udc_probe(struct udc *dev) spin_lock_init(&dev->lock); dev->gadget.ops = &udc_ops; - strcpy(dev->gadget.dev.bus_id, "gadget"); + dev_set_name(&dev->gadget.dev, "gadget"); dev->gadget.dev.release = gadget_release; dev->gadget.name = name; dev->gadget.name = name; diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index b6b2a0a5ba37..e2d8a5d86c40 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1687,6 +1687,19 @@ static int __init at91udc_probe(struct platform_device *pdev) udc->board.pullup_active_low); } + /* newer chips have more FIFO memory than rm9200 */ + if (cpu_is_at91sam9260()) { + udc->ep[0].maxpacket = 64; + udc->ep[3].maxpacket = 64; + udc->ep[4].maxpacket = 512; + udc->ep[5].maxpacket = 512; + } else if (cpu_is_at91sam9261()) { + udc->ep[3].maxpacket = 64; + } else if (cpu_is_at91sam9263()) { + udc->ep[0].maxpacket = 64; + udc->ep[3].maxpacket = 64; + } + udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1); if (!udc->udp_baseaddr) { retval = -ENOMEM; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c new file mode 100644 index 000000000000..d490d0289507 --- /dev/null +++ b/drivers/usb/gadget/cdc2.c @@ -0,0 +1,246 @@ +/* + * cdc2.c -- CDC Composite driver, with ECM and ACM support + * + * Copyright (C) 2008 David Brownell + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/utsname.h> + +#include "u_ether.h" +#include "u_serial.h" + + +#define DRIVER_DESC "CDC Composite Gadget" +#define DRIVER_VERSION "King Kamehameha Day 2008" + +/*-------------------------------------------------------------------------*/ + +/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. + */ + +/* Thanks to NetChip Technologies for donating this product ID. + * It's for devices with only this composite CDC configuration. + */ +#define CDC_VENDOR_NUM 0x0525 /* NetChip */ +#define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */ + +/*-------------------------------------------------------------------------*/ + +static struct usb_device_descriptor device_desc = { + .bLength = sizeof device_desc, + .bDescriptorType = USB_DT_DEVICE, + + .bcdUSB = __constant_cpu_to_le16(0x0200), + + .bDeviceClass = USB_CLASS_COMM, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + /* .bMaxPacketSize0 = f(hardware) */ + + /* Vendor and product id can be overridden by module parameters. */ + .idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM), + .idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM), + /* .bcdDevice = f(hardware) */ + /* .iManufacturer = DYNAMIC */ + /* .iProduct = DYNAMIC */ + /* NO SERIAL NUMBER */ + .bNumConfigurations = 1, +}; + +static struct usb_otg_descriptor otg_descriptor = { + .bLength = sizeof otg_descriptor, + .bDescriptorType = USB_DT_OTG, + + /* REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, +}; + +static const struct usb_descriptor_header *otg_desc[] = { + (struct usb_descriptor_header *) &otg_descriptor, + NULL, +}; + + +/* string IDs are assigned dynamically */ + +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 + +static char manufacturer[50]; + +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer, + [STRING_PRODUCT_IDX].s = DRIVER_DESC, + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_dev = { + .language = 0x0409, /* en-us */ + .strings = strings_dev, +}; + +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, +}; + +static u8 hostaddr[ETH_ALEN]; + +/*-------------------------------------------------------------------------*/ + +/* + * We _always_ have both CDC ECM and CDC ACM functions. + */ +static int __init cdc_do_config(struct usb_configuration *c) +{ + int status; + + if (gadget_is_otg(c->cdev->gadget)) { + c->descriptors = otg_desc; + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + status = ecm_bind_config(c, hostaddr); + if (status < 0) + return status; + + status = acm_bind_config(c, 0); + if (status < 0) + return status; + + return 0; +} + +static struct usb_configuration cdc_config_driver = { + .label = "CDC Composite (ECM + ACM)", + .bind = cdc_do_config, + .bConfigurationValue = 1, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* 2 mA, minimal */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init cdc_bind(struct usb_composite_dev *cdev) +{ + int gcnum; + struct usb_gadget *gadget = cdev->gadget; + int status; + + if (!can_support_ecm(cdev->gadget)) { + ERROR(cdev, "controller '%s' not usable\n", gadget->name); + return -EINVAL; + } + + /* set up network link layer */ + status = gether_setup(cdev->gadget, hostaddr); + if (status < 0) + return status; + + /* set up serial link layer */ + status = gserial_setup(cdev->gadget, 1); + if (status < 0) + goto fail0; + + gcnum = usb_gadget_controller_number(gadget); + if (gcnum >= 0) + device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); + else { + /* We assume that can_support_ecm() tells the truth; + * but if the controller isn't recognized at all then + * that assumption is a bit more likely to be wrong. + */ + WARN(cdev, "controller '%s' not recognized; trying %s\n", + gadget->name, + cdc_config_driver.label); + device_desc.bcdDevice = + __constant_cpu_to_le16(0x0300 | 0x0099); + } + + + /* Allocate string descriptor numbers ... note that string + * contents can be overridden by the composite_dev glue. + */ + + /* device descriptor strings: manufacturer, product */ + snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", + init_utsname()->sysname, init_utsname()->release, + gadget->name); + status = usb_string_id(cdev); + if (status < 0) + goto fail1; + strings_dev[STRING_MANUFACTURER_IDX].id = status; + device_desc.iManufacturer = status; + + status = usb_string_id(cdev); + if (status < 0) + goto fail1; + strings_dev[STRING_PRODUCT_IDX].id = status; + device_desc.iProduct = status; + + /* register our configuration */ + status = usb_add_config(cdev, &cdc_config_driver); + if (status < 0) + goto fail1; + + INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); + + return 0; + +fail1: + gserial_cleanup(); +fail0: + gether_cleanup(); + return status; +} + +static int __exit cdc_unbind(struct usb_composite_dev *cdev) +{ + gserial_cleanup(); + gether_cleanup(); + return 0; +} + +static struct usb_composite_driver cdc_driver = { + .name = "g_cdc", + .dev = &device_desc, + .strings = dev_strings, + .bind = cdc_bind, + .unbind = __exit_p(cdc_unbind), +}; + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("David Brownell"); +MODULE_LICENSE("GPL"); + +static int __init init(void) +{ + return usb_composite_register(&cdc_driver); +} +module_init(init); + +static void __exit cleanup(void) +{ + usb_composite_unregister(&cdc_driver); +} +module_exit(cleanup); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c new file mode 100644 index 000000000000..85c876c1f150 --- /dev/null +++ b/drivers/usb/gadget/composite.c @@ -0,0 +1,1041 @@ +/* + * composite.c - infrastructure for Composite USB Gadgets + * + * Copyright (C) 2006-2008 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kallsyms.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/device.h> + +#include <linux/usb/composite.h> + + +/* + * The code in this file is utility code, used to build a gadget driver + * from one or more "function" drivers, one or more "configuration" + * objects, and a "usb_composite_driver" by gluing them together along + * with the relevant device-wide data. + */ + +/* big enough to hold our biggest descriptor */ +#define USB_BUFSIZ 512 + +static struct usb_composite_driver *composite; + +/* Some systems will need runtime overrides for the product identifers + * published in the device descriptor, either numbers or strings or both. + * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). + */ + +static ushort idVendor; +module_param(idVendor, ushort, 0); +MODULE_PARM_DESC(idVendor, "USB Vendor ID"); + +static ushort idProduct; +module_param(idProduct, ushort, 0); +MODULE_PARM_DESC(idProduct, "USB Product ID"); + +static ushort bcdDevice; +module_param(bcdDevice, ushort, 0); +MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); + +static char *iManufacturer; +module_param(iManufacturer, charp, 0); +MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); + +static char *iProduct; +module_param(iProduct, charp, 0); +MODULE_PARM_DESC(iProduct, "USB Product string"); + +static char *iSerialNumber; +module_param(iSerialNumber, charp, 0); +MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); + +/*-------------------------------------------------------------------------*/ + +/** + * usb_add_function() - add a function to a configuration + * @config: the configuration + * @function: the function being added + * Context: single threaded during gadget setup + * + * After initialization, each configuration must have one or more + * functions added to it. Adding a function involves calling its @bind() + * method to allocate resources such as interface and string identifiers + * and endpoints. + * + * This function returns the value of the function's bind(), which is + * zero for success else a negative errno value. + */ +int __init usb_add_function(struct usb_configuration *config, + struct usb_function *function) +{ + int value = -EINVAL; + + DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n", + function->name, function, + config->label, config); + + if (!function->set_alt || !function->disable) + goto done; + + function->config = config; + list_add_tail(&function->list, &config->functions); + + /* REVISIT *require* function->bind? */ + if (function->bind) { + value = function->bind(config, function); + if (value < 0) { + list_del(&function->list); + function->config = NULL; + } + } else + value = 0; + + /* We allow configurations that don't work at both speeds. + * If we run into a lowspeed Linux system, treat it the same + * as full speed ... it's the function drivers that will need + * to avoid bulk and ISO transfers. + */ + if (!config->fullspeed && function->descriptors) + config->fullspeed = true; + if (!config->highspeed && function->hs_descriptors) + config->highspeed = true; + +done: + if (value) + DBG(config->cdev, "adding '%s'/%p --> %d\n", + function->name, function, value); + return value; +} + +/** + * usb_interface_id() - allocate an unused interface ID + * @config: configuration associated with the interface + * @function: function handling the interface + * Context: single threaded during gadget setup + * + * usb_interface_id() is called from usb_function.bind() callbacks to + * allocate new interface IDs. The function driver will then store that + * ID in interface, association, CDC union, and other descriptors. It + * will also handle any control requests targetted at that interface, + * particularly changing its altsetting via set_alt(). There may + * also be class-specific or vendor-specific requests to handle. + * + * All interface identifier should be allocated using this routine, to + * ensure that for example different functions don't wrongly assign + * different meanings to the same identifier. Note that since interface + * identifers are configuration-specific, functions used in more than + * one configuration (or more than once in a given configuration) need + * multiple versions of the relevant descriptors. + * + * Returns the interface ID which was allocated; or -ENODEV if no + * more interface IDs can be allocated. + */ +int __init usb_interface_id(struct usb_configuration *config, + struct usb_function *function) +{ + unsigned id = config->next_interface_id; + + if (id < MAX_CONFIG_INTERFACES) { + config->interface[id] = function; + config->next_interface_id = id + 1; + return id; + } + return -ENODEV; +} + +static int config_buf(struct usb_configuration *config, + enum usb_device_speed speed, void *buf, u8 type) +{ + struct usb_config_descriptor *c = buf; + void *next = buf + USB_DT_CONFIG_SIZE; + int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE; + struct usb_function *f; + int status; + + /* write the config descriptor */ + c = buf; + c->bLength = USB_DT_CONFIG_SIZE; + c->bDescriptorType = type; + /* wTotalLength is written later */ + c->bNumInterfaces = config->next_interface_id; + c->bConfigurationValue = config->bConfigurationValue; + c->iConfiguration = config->iConfiguration; + c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; + c->bMaxPower = config->bMaxPower; + + /* There may be e.g. OTG descriptors */ + if (config->descriptors) { + status = usb_descriptor_fillbuf(next, len, + config->descriptors); + if (status < 0) + return status; + len -= status; + next += status; + } + + /* add each function's descriptors */ + list_for_each_entry(f, &config->functions, list) { + struct usb_descriptor_header **descriptors; + + if (speed == USB_SPEED_HIGH) + descriptors = f->hs_descriptors; + else + descriptors = f->descriptors; + if (!descriptors) + continue; + status = usb_descriptor_fillbuf(next, len, + (const struct usb_descriptor_header **) descriptors); + if (status < 0) + return status; + len -= status; + next += status; + } + + len = next - buf; + c->wTotalLength = cpu_to_le16(len); + return len; +} + +static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) +{ + struct usb_gadget *gadget = cdev->gadget; + struct usb_configuration *c; + u8 type = w_value >> 8; + enum usb_device_speed speed = USB_SPEED_UNKNOWN; + + if (gadget_is_dualspeed(gadget)) { + int hs = 0; + + if (gadget->speed == USB_SPEED_HIGH) + hs = 1; + if (type == USB_DT_OTHER_SPEED_CONFIG) + hs = !hs; + if (hs) + speed = USB_SPEED_HIGH; + + } + + /* This is a lookup by config *INDEX* */ + w_value &= 0xff; + list_for_each_entry(c, &cdev->configs, list) { + /* ignore configs that won't work at this speed */ + if (speed == USB_SPEED_HIGH) { + if (!c->highspeed) + continue; + } else { + if (!c->fullspeed) + continue; + } + if (w_value == 0) + return config_buf(c, speed, cdev->req->buf, type); + w_value--; + } + return -EINVAL; +} + +static int count_configs(struct usb_composite_dev *cdev, unsigned type) +{ + struct usb_gadget *gadget = cdev->gadget; + struct usb_configuration *c; + unsigned count = 0; + int hs = 0; + + if (gadget_is_dualspeed(gadget)) { + if (gadget->speed == USB_SPEED_HIGH) + hs = 1; + if (type == USB_DT_DEVICE_QUALIFIER) + hs = !hs; + } + list_for_each_entry(c, &cdev->configs, list) { + /* ignore configs that won't work at this speed */ + if (hs) { + if (!c->highspeed) + continue; + } else { + if (!c->fullspeed) + continue; + } + count++; + } + return count; +} + +static void device_qual(struct usb_composite_dev *cdev) +{ + struct usb_qualifier_descriptor *qual = cdev->req->buf; + + qual->bLength = sizeof(*qual); + qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER; + /* POLICY: same bcdUSB and device type info at both speeds */ + qual->bcdUSB = cdev->desc.bcdUSB; + qual->bDeviceClass = cdev->desc.bDeviceClass; + qual->bDeviceSubClass = cdev->desc.bDeviceSubClass; + qual->bDeviceProtocol = cdev->desc.bDeviceProtocol; + /* ASSUME same EP0 fifo size at both speeds */ + qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0; + qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER); + qual->bRESERVED = 0; +} + +/*-------------------------------------------------------------------------*/ + +static void reset_config(struct usb_composite_dev *cdev) +{ + struct usb_function *f; + + DBG(cdev, "reset config\n"); + + list_for_each_entry(f, &cdev->config->functions, list) { + if (f->disable) + f->disable(f); + } + cdev->config = NULL; +} + +static int set_config(struct usb_composite_dev *cdev, + const struct usb_ctrlrequest *ctrl, unsigned number) +{ + struct usb_gadget *gadget = cdev->gadget; + struct usb_configuration *c = NULL; + int result = -EINVAL; + unsigned power = gadget_is_otg(gadget) ? 8 : 100; + int tmp; + + if (cdev->config) + reset_config(cdev); + + if (number) { + list_for_each_entry(c, &cdev->configs, list) { + if (c->bConfigurationValue == number) { + result = 0; + break; + } + } + if (result < 0) + goto done; + } else + result = 0; + + INFO(cdev, "%s speed config #%d: %s\n", + ({ char *speed; + switch (gadget->speed) { + case USB_SPEED_LOW: speed = "low"; break; + case USB_SPEED_FULL: speed = "full"; break; + case USB_SPEED_HIGH: speed = "high"; break; + default: speed = "?"; break; + } ; speed; }), number, c ? c->label : "unconfigured"); + + if (!c) + goto done; + + cdev->config = c; + + /* Initialize all interfaces by setting them to altsetting zero. */ + for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { + struct usb_function *f = c->interface[tmp]; + + if (!f) + break; + + result = f->set_alt(f, tmp, 0); + if (result < 0) { + DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", + tmp, f->name, f, result); + + reset_config(cdev); + goto done; + } + } + + /* when we return, be sure our power usage is valid */ + power = 2 * c->bMaxPower; +done: + usb_gadget_vbus_draw(gadget, power); + return result; +} + +/** + * usb_add_config() - add a configuration to a device. + * @cdev: wraps the USB gadget + * @config: the configuration, with bConfigurationValue assigned + * Context: single threaded during gadget setup + * + * One of the main tasks of a composite driver's bind() routine is to + * add each of the configurations it supports, using this routine. + * + * This function returns the value of the configuration's bind(), which + * is zero for success else a negative errno value. Binding configurations + * assigns global resources including string IDs, and per-configuration + * resources such as interface IDs and endpoints. + */ +int __init usb_add_config(struct usb_composite_dev *cdev, + struct usb_configuration *config) +{ + int status = -EINVAL; + struct usb_configuration *c; + + DBG(cdev, "adding config #%u '%s'/%p\n", + config->bConfigurationValue, + config->label, config); + + if (!config->bConfigurationValue || !config->bind) + goto done; + + /* Prevent duplicate configuration identifiers */ + list_for_each_entry(c, &cdev->configs, list) { + if (c->bConfigurationValue == config->bConfigurationValue) { + status = -EBUSY; + goto done; + } + } + + config->cdev = cdev; + list_add_tail(&config->list, &cdev->configs); + + INIT_LIST_HEAD(&config->functions); + config->next_interface_id = 0; + + status = config->bind(config); + if (status < 0) { + list_del(&config->list); + config->cdev = NULL; + } else { + unsigned i; + + DBG(cdev, "cfg %d/%p speeds:%s%s\n", + config->bConfigurationValue, config, + config->highspeed ? " high" : "", + config->fullspeed + ? (gadget_is_dualspeed(cdev->gadget) + ? " full" + : " full/low") + : ""); + + for (i = 0; i < MAX_CONFIG_INTERFACES; i++) { + struct usb_function *f = config->interface[i]; + + if (!f) + continue; + DBG(cdev, " interface %d = %s/%p\n", + i, f->name, f); + } + } + + /* set_alt(), or next config->bind(), sets up + * ep->driver_data as needed. + */ + usb_ep_autoconfig_reset(cdev->gadget); + +done: + if (status) + DBG(cdev, "added config '%s'/%u --> %d\n", config->label, + config->bConfigurationValue, status); + return status; +} + +/*-------------------------------------------------------------------------*/ + +/* We support strings in multiple languages ... string descriptor zero + * says which languages are supported. The typical case will be that + * only one language (probably English) is used, with I18N handled on + * the host side. + */ + +static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf) +{ + const struct usb_gadget_strings *s; + u16 language; + __le16 *tmp; + + while (*sp) { + s = *sp; + language = cpu_to_le16(s->language); + for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) { + if (*tmp == language) + goto repeat; + } + *tmp++ = language; +repeat: + sp++; + } +} + +static int lookup_string( + struct usb_gadget_strings **sp, + void *buf, + u16 language, + int id +) +{ + struct usb_gadget_strings *s; + int value; + + while (*sp) { + s = *sp++; + if (s->language != language) + continue; + value = usb_gadget_get_string(s, id, buf); + if (value > 0) + return value; + } + return -EINVAL; +} + +static int get_string(struct usb_composite_dev *cdev, + void *buf, u16 language, int id) +{ + struct usb_configuration *c; + struct usb_function *f; + int len; + + /* Yes, not only is USB's I18N support probably more than most + * folk will ever care about ... also, it's all supported here. + * (Except for UTF8 support for Unicode's "Astral Planes".) + */ + + /* 0 == report all available language codes */ + if (id == 0) { + struct usb_string_descriptor *s = buf; + struct usb_gadget_strings **sp; + + memset(s, 0, 256); + s->bDescriptorType = USB_DT_STRING; + + sp = composite->strings; + if (sp) + collect_langs(sp, s->wData); + + list_for_each_entry(c, &cdev->configs, list) { + sp = c->strings; + if (sp) + collect_langs(sp, s->wData); + + list_for_each_entry(f, &c->functions, list) { + sp = f->strings; + if (sp) + collect_langs(sp, s->wData); + } + } + + for (len = 0; s->wData[len] && len <= 126; len++) + continue; + if (!len) + return -EINVAL; + + s->bLength = 2 * (len + 1); + return s->bLength; + } + + /* Otherwise, look up and return a specified string. String IDs + * are device-scoped, so we look up each string table we're told + * about. These lookups are infrequent; simpler-is-better here. + */ + if (composite->strings) { + len = lookup_string(composite->strings, buf, language, id); + if (len > 0) + return len; + } + list_for_each_entry(c, &cdev->configs, list) { + if (c->strings) { + len = lookup_string(c->strings, buf, language, id); + if (len > 0) + return len; + } + list_for_each_entry(f, &c->functions, list) { + if (!f->strings) + continue; + len = lookup_string(f->strings, buf, language, id); + if (len > 0) + return len; + } + } + return -EINVAL; +} + +/** + * usb_string_id() - allocate an unused string ID + * @cdev: the device whose string descriptor IDs are being allocated + * Context: single threaded during gadget setup + * + * @usb_string_id() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then store that ID in the appropriate descriptors and string table. + * + * All string identifier should be allocated using this routine, to + * ensure that for example different functions don't wrongly assign + * different meanings to the same identifier. + */ +int __init usb_string_id(struct usb_composite_dev *cdev) +{ + if (cdev->next_string_id < 254) { + /* string id 0 is reserved */ + cdev->next_string_id++; + return cdev->next_string_id; + } + return -ENODEV; +} + +/*-------------------------------------------------------------------------*/ + +static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) +{ + if (req->status || req->actual != req->length) + DBG((struct usb_composite_dev *) ep->driver_data, + "setup complete --> %d, %d/%d\n", + req->status, req->actual, req->length); +} + +/* + * The setup() callback implements all the ep0 functionality that's + * not handled lower down, in hardware or the hardware driver(like + * device and endpoint feature flags, and their status). It's all + * housekeeping for the gadget function we're implementing. Most of + * the work is in config and function specific setup. + */ +static int +composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_request *req = cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + struct usb_function *f = NULL; + + /* partial re-init of the response message; the function or the + * gadget might need to intercept e.g. a control-OUT completion + * when we delegate to it. + */ + req->zero = 0; + req->complete = composite_setup_complete; + req->length = USB_BUFSIZ; + gadget->ep0->driver_data = cdev; + + switch (ctrl->bRequest) { + + /* we handle all standard USB descriptors */ + case USB_REQ_GET_DESCRIPTOR: + if (ctrl->bRequestType != USB_DIR_IN) + goto unknown; + switch (w_value >> 8) { + + case USB_DT_DEVICE: + cdev->desc.bNumConfigurations = + count_configs(cdev, USB_DT_DEVICE); + value = min(w_length, (u16) sizeof cdev->desc); + memcpy(req->buf, &cdev->desc, value); + break; + case USB_DT_DEVICE_QUALIFIER: + if (!gadget_is_dualspeed(gadget)) + break; + device_qual(cdev); + value = min_t(int, w_length, + sizeof(struct usb_qualifier_descriptor)); + break; + case USB_DT_OTHER_SPEED_CONFIG: + if (!gadget_is_dualspeed(gadget)) + break; + /* FALLTHROUGH */ + case USB_DT_CONFIG: + value = config_desc(cdev, w_value); + if (value >= 0) + value = min(w_length, (u16) value); + break; + case USB_DT_STRING: + value = get_string(cdev, req->buf, + w_index, w_value & 0xff); + if (value >= 0) + value = min(w_length, (u16) value); + break; + } + break; + + /* any number of configs can work */ + case USB_REQ_SET_CONFIGURATION: + if (ctrl->bRequestType != 0) + goto unknown; + if (gadget_is_otg(gadget)) { + if (gadget->a_hnp_support) + DBG(cdev, "HNP available\n"); + else if (gadget->a_alt_hnp_support) + DBG(cdev, "HNP on another port\n"); + else + VDBG(cdev, "HNP inactive\n"); + } + spin_lock(&cdev->lock); + value = set_config(cdev, ctrl, w_value); + spin_unlock(&cdev->lock); + break; + case USB_REQ_GET_CONFIGURATION: + if (ctrl->bRequestType != USB_DIR_IN) + goto unknown; + if (cdev->config) + *(u8 *)req->buf = cdev->config->bConfigurationValue; + else + *(u8 *)req->buf = 0; + value = min(w_length, (u16) 1); + break; + + /* function drivers must handle get/set altsetting; if there's + * no get() method, we know only altsetting zero works. + */ + case USB_REQ_SET_INTERFACE: + if (ctrl->bRequestType != USB_RECIP_INTERFACE) + goto unknown; + if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[w_index]; + if (!f) + break; + if (w_value && !f->get_alt) + break; + value = f->set_alt(f, w_index, w_value); + break; + case USB_REQ_GET_INTERFACE: + if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) + goto unknown; + if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[w_index]; + if (!f) + break; + /* lots of interfaces only need altsetting zero... */ + value = f->get_alt ? f->get_alt(f, w_index) : 0; + if (value < 0) + break; + *((u8 *)req->buf) = value; + value = min(w_length, (u16) 1); + break; + default: +unknown: + VDBG(cdev, + "non-core control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + + /* functions always handle their interfaces ... punt other + * recipients (endpoint, other, WUSB, ...) to the current + * configuration code. + * + * REVISIT it could make sense to let the composite device + * take such requests too, if that's ever needed: to work + * in config 0, etc. + */ + if ((ctrl->bRequestType & USB_RECIP_MASK) + == USB_RECIP_INTERFACE) { + f = cdev->config->interface[w_index]; + if (f && f->setup) + value = f->setup(f, ctrl); + else + f = NULL; + } + if (value < 0 && !f) { + struct usb_configuration *c; + + c = cdev->config; + if (c && c->setup) + value = c->setup(c, ctrl); + } + + goto done; + } + + /* respond with data transfer before status phase? */ + if (value >= 0) { + req->length = value; + req->zero = value < w_length; + value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); + if (value < 0) { + DBG(cdev, "ep_queue --> %d\n", value); + req->status = 0; + composite_setup_complete(gadget->ep0, req); + } + } + +done: + /* device either stalls (value < 0) or reports success */ + return value; +} + +static void composite_disconnect(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + unsigned long flags; + + /* REVISIT: should we have config and device level + * disconnect callbacks? + */ + spin_lock_irqsave(&cdev->lock, flags); + if (cdev->config) + reset_config(cdev); + spin_unlock_irqrestore(&cdev->lock, flags); +} + +/*-------------------------------------------------------------------------*/ + +static void /* __init_or_exit */ +composite_unbind(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + + /* composite_disconnect() must already have been called + * by the underlying peripheral controller driver! + * so there's no i/o concurrency that could affect the + * state protected by cdev->lock. + */ + WARN_ON(cdev->config); + + while (!list_empty(&cdev->configs)) { + struct usb_configuration *c; + + c = list_first_entry(&cdev->configs, + struct usb_configuration, list); + while (!list_empty(&c->functions)) { + struct usb_function *f; + + f = list_first_entry(&c->functions, + struct usb_function, list); + list_del(&f->list); + if (f->unbind) { + DBG(cdev, "unbind function '%s'/%p\n", + f->name, f); + f->unbind(c, f); + /* may free memory for "f" */ + } + } + list_del(&c->list); + if (c->unbind) { + DBG(cdev, "unbind config '%s'/%p\n", c->label, c); + c->unbind(c); + /* may free memory for "c" */ + } + } + if (composite->unbind) + composite->unbind(cdev); + + if (cdev->req) { + kfree(cdev->req->buf); + usb_ep_free_request(gadget->ep0, cdev->req); + } + kfree(cdev); + set_gadget_data(gadget, NULL); + composite = NULL; +} + +static void __init +string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s) +{ + struct usb_string *str = tab->strings; + + for (str = tab->strings; str->s; str++) { + if (str->id == id) { + str->s = s; + return; + } + } +} + +static void __init +string_override(struct usb_gadget_strings **tab, u8 id, const char *s) +{ + while (*tab) { + string_override_one(*tab, id, s); + tab++; + } +} + +static int __init composite_bind(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + int status = -ENOMEM; + + cdev = kzalloc(sizeof *cdev, GFP_KERNEL); + if (!cdev) + return status; + + spin_lock_init(&cdev->lock); + cdev->gadget = gadget; + set_gadget_data(gadget, cdev); + INIT_LIST_HEAD(&cdev->configs); + + /* preallocate control response and buffer */ + cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); + if (!cdev->req) + goto fail; + cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); + if (!cdev->req->buf) + goto fail; + cdev->req->complete = composite_setup_complete; + gadget->ep0->driver_data = cdev; + + cdev->bufsiz = USB_BUFSIZ; + cdev->driver = composite; + + usb_gadget_set_selfpowered(gadget); + + /* interface and string IDs start at zero via kzalloc. + * we force endpoints to start unassigned; few controller + * drivers will zero ep->driver_data. + */ + usb_ep_autoconfig_reset(cdev->gadget); + + /* composite gadget needs to assign strings for whole device (like + * serial number), register function drivers, potentially update + * power state and consumption, etc + */ + status = composite->bind(cdev); + if (status < 0) + goto fail; + + cdev->desc = *composite->dev; + cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; + + /* standardized runtime overrides for device ID data */ + if (idVendor) + cdev->desc.idVendor = cpu_to_le16(idVendor); + if (idProduct) + cdev->desc.idProduct = cpu_to_le16(idProduct); + if (bcdDevice) + cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); + + /* strings can't be assigned before bind() allocates the + * releavnt identifiers + */ + if (cdev->desc.iManufacturer && iManufacturer) + string_override(composite->strings, + cdev->desc.iManufacturer, iManufacturer); + if (cdev->desc.iProduct && iProduct) + string_override(composite->strings, + cdev->desc.iProduct, iProduct); + if (cdev->desc.iSerialNumber && iSerialNumber) + string_override(composite->strings, + cdev->desc.iSerialNumber, iSerialNumber); + + INFO(cdev, "%s ready\n", composite->name); + return 0; + +fail: + composite_unbind(gadget); + return status; +} + +/*-------------------------------------------------------------------------*/ + +static void +composite_suspend(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_function *f; + + /* REVISIT: should we have config and device level + * suspend/resume callbacks? + */ + DBG(cdev, "suspend\n"); + if (cdev->config) { + list_for_each_entry(f, &cdev->config->functions, list) { + if (f->suspend) + f->suspend(f); + } + } +} + +static void +composite_resume(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_function *f; + + /* REVISIT: should we have config and device level + * suspend/resume callbacks? + */ + DBG(cdev, "resume\n"); + if (cdev->config) { + list_for_each_entry(f, &cdev->config->functions, list) { + if (f->resume) + f->resume(f); + } + } +} + +/*-------------------------------------------------------------------------*/ + +static struct usb_gadget_driver composite_driver = { + .speed = USB_SPEED_HIGH, + + .bind = composite_bind, + .unbind = __exit_p(composite_unbind), + + .setup = composite_setup, + .disconnect = composite_disconnect, + + .suspend = composite_suspend, + .resume = composite_resume, + + .driver = { + .owner = THIS_MODULE, + }, +}; + +/** + * usb_composite_register() - register a composite driver + * @driver: the driver to register + * Context: single threaded during gadget setup + * + * This function is used to register drivers using the composite driver + * framework. The return value is zero, or a negative errno value. + * Those values normally come from the driver's @bind method, which does + * all the work of setting up the driver to match the hardware. + * + * On successful return, the gadget is ready to respond to requests from + * the host, unless one of its components invokes usb_gadget_disconnect() + * while it was binding. That would usually be done in order to wait for + * some userspace participation. + */ +int __init usb_composite_register(struct usb_composite_driver *driver) +{ + if (!driver || !driver->dev || !driver->bind || composite) + return -EINVAL; + + if (!driver->name) + driver->name = "composite"; + composite_driver.function = (char *) driver->name; + composite_driver.driver.name = driver->name; + composite = driver; + + return usb_gadget_register_driver(&composite_driver); +} + +/** + * usb_composite_unregister() - unregister a composite driver + * @driver: the driver to unregister + * + * This function is used to unregister drivers using the composite + * driver framework. + */ +void __exit usb_composite_unregister(struct usb_composite_driver *driver) +{ + if (composite != driver) + return; + usb_gadget_unregister_driver(&composite_driver); +} diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index a4e54b2743f0..1ca1c326392a 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -96,7 +96,7 @@ int usb_gadget_config_buf( /* config descriptor first */ if (length < USB_DT_CONFIG_SIZE || !desc) return -EINVAL; - *cp = *config; + *cp = *config; /* then interface/endpoint/class/vendor/... */ len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, @@ -115,3 +115,77 @@ int usb_gadget_config_buf( return len; } +/** + * usb_copy_descriptors - copy a vector of USB descriptors + * @src: null-terminated vector to copy + * Context: initialization code, which may sleep + * + * This makes a copy of a vector of USB descriptors. Its primary use + * is to support usb_function objects which can have multiple copies, + * each needing different descriptors. Functions may have static + * tables of descriptors, which are used as templates and customized + * with identifiers (for interfaces, strings, endpoints, and more) + * as needed by a given function instance. + */ +struct usb_descriptor_header **__init +usb_copy_descriptors(struct usb_descriptor_header **src) +{ + struct usb_descriptor_header **tmp; + unsigned bytes; + unsigned n_desc; + void *mem; + struct usb_descriptor_header **ret; + + /* count descriptors and their sizes; then add vector size */ + for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) + bytes += (*tmp)->bLength; + bytes += (n_desc + 1) * sizeof(*tmp); + + mem = kmalloc(bytes, GFP_KERNEL); + if (!mem) + return NULL; + + /* fill in pointers starting at "tmp", + * to descriptors copied starting at "mem"; + * and return "ret" + */ + tmp = mem; + ret = mem; + mem += (n_desc + 1) * sizeof(*tmp); + while (*src) { + memcpy(mem, *src, (*src)->bLength); + *tmp = mem; + tmp++; + mem += (*src)->bLength; + src++; + } + *tmp = NULL; + + return ret; +} + +/** + * usb_find_endpoint - find a copy of an endpoint descriptor + * @src: original vector of descriptors + * @copy: copy of @src + * @ep: endpoint descriptor found in @src + * + * This returns the copy of the @match descriptor made for @copy. Its + * intended use is to help remembering the endpoint descriptor to use + * when enabling a given endpoint. + */ +struct usb_endpoint_descriptor *__init +usb_find_endpoint( + struct usb_descriptor_header **src, + struct usb_descriptor_header **copy, + struct usb_endpoint_descriptor *match +) +{ + while (*src) { + if (*src == (void *) match) + return (void *)*copy; + src++; + copy++; + } + return NULL; +} diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 42036192a03c..21d1406af9ee 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -862,7 +862,7 @@ static int dummy_udc_probe (struct platform_device *pdev) /* maybe claim OTG support, though we won't complete HNP */ dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); - strcpy (dum->gadget.dev.bus_id, "gadget"); + dev_set_name(&dum->gadget.dev, "gadget"); dum->gadget.dev.parent = &pdev->dev; dum->gadget.dev.release = dummy_gadget_release; rc = device_register (&dum->gadget.dev); @@ -1865,7 +1865,7 @@ static int dummy_hcd_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); - hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; the_controller = hcd_to_dummy (hcd); diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 8bdad221fa91..9462e30192d8 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -159,6 +159,7 @@ ep_matches ( /* MATCH!! */ /* report address */ + desc->bEndpointAddress &= USB_DIR_IN; if (isdigit (ep->name [2])) { u8 num = simple_strtol (&ep->name [2], NULL, 10); desc->bEndpointAddress |= num; diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 4ce3950b997f..d7aaaa29b1e1 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1,8 +1,9 @@ /* * ether.c -- Ethernet gadget driver, with CDC and non-CDC options * - * Copyright (C) 2003-2005 David Brownell + * Copyright (C) 2003-2005,2008 David Brownell * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger + * Copyright (C) 2008 Nokia Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,18 +24,9 @@ #include <linux/kernel.h> #include <linux/utsname.h> -#include <linux/device.h> -#include <linux/ctype.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/usb/ch9.h> -#include <linux/usb/cdc.h> -#include <linux/usb/gadget.h> +#include "u_ether.h" -#include "gadget_chips.h" - -/*-------------------------------------------------------------------------*/ /* * Ethernet gadget driver -- with CDC and non-CDC options @@ -46,7 +38,11 @@ * this USB-IF standard as its open-systems interoperability solution; * most host side USB stacks (except from Microsoft) support it. * - * There's some hardware that can't talk CDC. We make that hardware + * This is sometimes called "CDC ECM" (Ethernet Control Model) to support + * TLA-soup. "CDC ACM" (Abstract Control Model) is for modems, and a new + * "CDC EEM" (Ethernet Emulation Model) is starting to spread. + * + * There's some hardware that can't talk CDC ECM. We make that hardware * implement a "minimalist" vendor-agnostic CDC core: same framing, but * link-level setup only requires activating the configuration. Only the * endpoint descriptors, and product/vendor IDs, are relevant; no control @@ -64,70 +60,40 @@ * A third option is also in use. Rather than CDC Ethernet, or something * simpler, Microsoft pushes their own approach: RNDIS. The published * RNDIS specs are ambiguous and appear to be incomplete, and are also - * needlessly complex. + * needlessly complex. They borrow more from CDC ACM than CDC ECM. */ #define DRIVER_DESC "Ethernet Gadget" -#define DRIVER_VERSION "May Day 2005" - -static const char shortname [] = "ether"; -static const char driver_desc [] = DRIVER_DESC; - -#define RX_EXTRA 20 /* guard against rx overflows */ - -#include "rndis.h" +#define DRIVER_VERSION "Memorial Day 2008" -#ifndef CONFIG_USB_ETH_RNDIS -#define rndis_uninit(x) do{}while(0) -#define rndis_deregister(c) do{}while(0) -#define rndis_exit() do{}while(0) +#ifdef CONFIG_USB_ETH_RNDIS +#define PREFIX "RNDIS/" +#else +#define PREFIX "" #endif -/* CDC and RNDIS support the same host-chosen outgoing packet filters. */ -#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ - |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ - |USB_CDC_PACKET_TYPE_PROMISCUOUS \ - |USB_CDC_PACKET_TYPE_DIRECTED) - - -/*-------------------------------------------------------------------------*/ - -struct eth_dev { - spinlock_t lock; - struct usb_gadget *gadget; - struct usb_request *req; /* for control responses */ - struct usb_request *stat_req; /* for cdc & rndis status */ - - u8 config; - struct usb_ep *in_ep, *out_ep, *status_ep; - const struct usb_endpoint_descriptor - *in, *out, *status; - - spinlock_t req_lock; - struct list_head tx_reqs, rx_reqs; - - struct net_device *net; - struct net_device_stats stats; - atomic_t tx_qlen; - - struct work_struct work; - unsigned zlp:1; - unsigned cdc:1; - unsigned rndis:1; - unsigned suspended:1; - u16 cdc_filter; - unsigned long todo; -#define WORK_RX_MEMORY 0 - int rndis_config; - u8 host_mac [ETH_ALEN]; -}; - -/* This version autoconfigures as much as possible at run-time. +/* + * This driver aims for interoperability by using CDC ECM unless + * + * can_support_ecm() + * + * returns false, in which case it supports the CDC Subset. By default, + * that returns true; most hardware has no problems with CDC ECM, that's + * a good default. Previous versions of this driver had no default; this + * version changes that, removing overhead for new controller support. * - * It also ASSUMES a self-powered device, without remote wakeup, - * although remote wakeup support would make sense. + * IF YOUR HARDWARE CAN'T SUPPORT CDC ECM, UPDATE THAT ROUTINE! */ +static inline bool has_rndis(void) +{ +#ifdef CONFIG_USB_ETH_RNDIS + return true; +#else + return false; +#endif +} + /*-------------------------------------------------------------------------*/ /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! @@ -137,8 +103,8 @@ struct eth_dev { /* Thanks to NetChip Technologies for donating this product ID. * It's for devices with only CDC Ethernet configurations. */ -#define CDC_VENDOR_NUM 0x0525 /* NetChip */ -#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ +#define CDC_VENDOR_NUM 0x0525 /* NetChip */ +#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ /* For hardware that can't talk CDC, we use the same vendor ID that * ARM Linux has used for ethernet-over-usb, both with sa1100 and @@ -162,274 +128,9 @@ struct eth_dev { #define RNDIS_VENDOR_NUM 0x0525 /* NetChip */ #define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */ - -/* Some systems will want different product identifers published in the - * device descriptor, either numbers or strings or both. These string - * parameters are in UTF-8 (superset of ASCII's 7 bit characters). - */ - -static ushort idVendor; -module_param(idVendor, ushort, S_IRUGO); -MODULE_PARM_DESC(idVendor, "USB Vendor ID"); - -static ushort idProduct; -module_param(idProduct, ushort, S_IRUGO); -MODULE_PARM_DESC(idProduct, "USB Product ID"); - -static ushort bcdDevice; -module_param(bcdDevice, ushort, S_IRUGO); -MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); - -static char *iManufacturer; -module_param(iManufacturer, charp, S_IRUGO); -MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); - -static char *iProduct; -module_param(iProduct, charp, S_IRUGO); -MODULE_PARM_DESC(iProduct, "USB Product string"); - -static char *iSerialNumber; -module_param(iSerialNumber, charp, S_IRUGO); -MODULE_PARM_DESC(iSerialNumber, "SerialNumber"); - -/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ -static char *dev_addr; -module_param(dev_addr, charp, S_IRUGO); -MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); - -/* this address is invisible to ifconfig */ -static char *host_addr; -module_param(host_addr, charp, S_IRUGO); -MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); - - -/*-------------------------------------------------------------------------*/ - -/* Include CDC support if we could run on CDC-capable hardware. */ - -#ifdef CONFIG_USB_GADGET_NET2280 -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_DUMMY_HCD -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_GOKU -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_LH7A40X -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_MQ11XX -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_OMAP -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_N9604 -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_S3C2410 -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_AT91 -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_MUSBHSFC -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_MUSB_HDRC -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_ATMEL_USBA -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_FSL_USB2 -#define DEV_CONFIG_CDC -#endif - -/* For CDC-incapable hardware, choose the simple cdc subset. - * Anything that talks bulk (without notable bugs) can do this. - */ -#ifdef CONFIG_USB_GADGET_PXA25X -#define DEV_CONFIG_SUBSET -#endif - -#ifdef CONFIG_USB_GADGET_PXA27X -#define DEV_CONFIG_SUBSET -#endif - -#ifdef CONFIG_USB_GADGET_SUPERH -#define DEV_CONFIG_SUBSET -#endif - -#ifdef CONFIG_USB_GADGET_SA1100 -/* use non-CDC for backwards compatibility */ -#define DEV_CONFIG_SUBSET -#endif - -#ifdef CONFIG_USB_GADGET_M66592 -#define DEV_CONFIG_CDC -#endif - -#ifdef CONFIG_USB_GADGET_AMD5536UDC -#define DEV_CONFIG_CDC -#endif - - -/*-------------------------------------------------------------------------*/ - -/* "main" config is either CDC, or its simple subset */ -static inline int is_cdc(struct eth_dev *dev) -{ -#if !defined(DEV_CONFIG_SUBSET) - return 1; /* only cdc possible */ -#elif !defined (DEV_CONFIG_CDC) - return 0; /* only subset possible */ -#else - return dev->cdc; /* depends on what hardware we found */ -#endif -} - -/* "secondary" RNDIS config may sometimes be activated */ -static inline int rndis_active(struct eth_dev *dev) -{ -#ifdef CONFIG_USB_ETH_RNDIS - return dev->rndis; -#else - return 0; -#endif -} - -#define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev)) -#define cdc_active(dev) ( is_cdc(dev) && !rndis_active(dev)) - - - -#define DEFAULT_QLEN 2 /* double buffering by default */ - -/* peak bulk transfer bits-per-second */ -#define HS_BPS (13 * 512 * 8 * 1000 * 8) -#define FS_BPS (19 * 64 * 1 * 1000 * 8) - -#ifdef CONFIG_USB_GADGET_DUALSPEED -#define DEVSPEED USB_SPEED_HIGH - -static unsigned qmult = 5; -module_param (qmult, uint, S_IRUGO|S_IWUSR); - - -/* for dual-speed hardware, use deeper queues at highspeed */ -#define qlen(gadget) \ - (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1)) - -static inline int BITRATE(struct usb_gadget *g) -{ - return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS; -} - -#else /* full speed (low speed doesn't do bulk) */ - -#define qmult 1 - -#define DEVSPEED USB_SPEED_FULL - -#define qlen(gadget) DEFAULT_QLEN - -static inline int BITRATE(struct usb_gadget *g) -{ - return FS_BPS; -} -#endif - - -/*-------------------------------------------------------------------------*/ - -#define xprintk(d,level,fmt,args...) \ - printk(level "%s: " fmt , (d)->net->name , ## args) - -#ifdef DEBUG -#undef DEBUG -#define DEBUG(dev,fmt,args...) \ - xprintk(dev , KERN_DEBUG , fmt , ## args) -#else -#define DEBUG(dev,fmt,args...) \ - do { } while (0) -#endif /* DEBUG */ - -#ifdef VERBOSE_DEBUG -#define VDEBUG DEBUG -#else -#define VDEBUG(dev,fmt,args...) \ - do { } while (0) -#endif /* DEBUG */ - -#define ERROR(dev,fmt,args...) \ - xprintk(dev , KERN_ERR , fmt , ## args) -#define WARN(dev,fmt,args...) \ - xprintk(dev , KERN_WARNING , fmt , ## args) -#define INFO(dev,fmt,args...) \ - xprintk(dev , KERN_INFO , fmt , ## args) - /*-------------------------------------------------------------------------*/ -/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly - * ep0 implementation: descriptors, config management, setup(). - * also optional class-specific notification interrupt transfer. - */ - -/* - * DESCRIPTORS ... most are static, but strings and (full) configuration - * descriptors are built on demand. For now we do either full CDC, or - * our simple subset, with RNDIS as an optional second configuration. - * - * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet. But - * the class descriptors match a modem (they're ignored; it's really just - * Ethernet functionality), they don't need the NOP altsetting, and the - * status transfer endpoint isn't optional. - */ - -#define STRING_MANUFACTURER 1 -#define STRING_PRODUCT 2 -#define STRING_ETHADDR 3 -#define STRING_DATA 4 -#define STRING_CONTROL 5 -#define STRING_RNDIS_CONTROL 6 -#define STRING_CDC 7 -#define STRING_SUBSET 8 -#define STRING_RNDIS 9 -#define STRING_SERIALNUMBER 10 - -/* holds our biggest descriptor (or RNDIS response) */ -#define USB_BUFSIZ 256 - -/* - * This device advertises one configuration, eth_config, unless RNDIS - * is enabled (rndis_config) on hardware supporting at least two configs. - * - * NOTE: Controllers like superh_udc should probably be able to use - * an RNDIS-only configuration. - * - * FIXME define some higher-powered configurations to make it easier - * to recharge batteries ... - */ - -#define DEV_CONFIG_VALUE 1 /* cdc or subset */ -#define DEV_RNDIS_CONFIG_VALUE 2 /* rndis; optional */ - -static struct usb_device_descriptor -device_desc = { +static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -438,2220 +139,234 @@ device_desc = { .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, .bDeviceProtocol = 0, + /* .bMaxPacketSize0 = f(hardware) */ + /* Vendor and product id defaults change according to what configs + * we support. (As does bNumConfigurations.) These values can + * also be overridden by module parameters. + */ .idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM), .idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM), - .iManufacturer = STRING_MANUFACTURER, - .iProduct = STRING_PRODUCT, + /* .bcdDevice = f(hardware) */ + /* .iManufacturer = DYNAMIC */ + /* .iProduct = DYNAMIC */ + /* NO SERIAL NUMBER */ .bNumConfigurations = 1, }; -static struct usb_otg_descriptor -otg_descriptor = { +static struct usb_otg_descriptor otg_descriptor = { .bLength = sizeof otg_descriptor, .bDescriptorType = USB_DT_OTG, - .bmAttributes = USB_OTG_SRP, -}; - -static struct usb_config_descriptor -eth_config = { - .bLength = sizeof eth_config, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 2, - .bConfigurationValue = DEV_CONFIG_VALUE, - .iConfiguration = STRING_CDC, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 50, -}; - -#ifdef CONFIG_USB_ETH_RNDIS -static struct usb_config_descriptor -rndis_config = { - .bLength = sizeof rndis_config, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 2, - .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE, - .iConfiguration = STRING_RNDIS, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 50, -}; -#endif - -/* - * Compared to the simple CDC subset, the full CDC Ethernet model adds - * three class descriptors, two interface descriptors, optional status - * endpoint. Both have a "data" interface and two bulk endpoints. - * There are also differences in how control requests are handled. - * - * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the - * CDC-ACM (modem) spec. Unfortunately MSFT's RNDIS driver is buggy; it - * may hang or oops. Since bugfixes (or accurate specs, letting Linux - * work around those bugs) are unlikely to ever come from MSFT, you may - * wish to avoid using RNDIS. - * - * MCCI offers an alternative to RNDIS if you need to connect to Windows - * but have hardware that can't support CDC Ethernet. We add descriptors - * to present the CDC Subset as a (nonconformant) CDC MDLM variant called - * "SAFE". That borrows from both CDC Ethernet and CDC MDLM. You can - * get those drivers from MCCI, or bundled with various products. - */ - -#ifdef DEV_CONFIG_CDC -static struct usb_interface_descriptor -control_intf = { - .bLength = sizeof control_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 0, - /* status endpoint is optional; this may be patched later */ - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .iInterface = STRING_CONTROL, -}; -#endif - -#ifdef CONFIG_USB_ETH_RNDIS -static const struct usb_interface_descriptor -rndis_control_intf = { - .bLength = sizeof rndis_control_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR, - .iInterface = STRING_RNDIS_CONTROL, -}; -#endif - -static const struct usb_cdc_header_desc header_desc = { - .bLength = sizeof header_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_HEADER_TYPE, - - .bcdCDC = __constant_cpu_to_le16 (0x0110), -}; - -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - -static const struct usb_cdc_union_desc union_desc = { - .bLength = sizeof union_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_UNION_TYPE, - - .bMasterInterface0 = 0, /* index of control interface */ - .bSlaveInterface0 = 1, /* index of DATA interface */ -}; - -#endif /* CDC || RNDIS */ - -#ifdef CONFIG_USB_ETH_RNDIS - -static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { - .bLength = sizeof call_mgmt_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, - - .bmCapabilities = 0x00, - .bDataInterface = 0x01, -}; - -static const struct usb_cdc_acm_descriptor acm_descriptor = { - .bLength = sizeof acm_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ACM_TYPE, - - .bmCapabilities = 0x00, -}; - -#endif - -#ifndef DEV_CONFIG_CDC - -/* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various - * ways: data endpoints live in the control interface, there's no data - * interface, and it's not used to talk to a cell phone radio. - */ - -static const struct usb_cdc_mdlm_desc mdlm_desc = { - .bLength = sizeof mdlm_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_MDLM_TYPE, - - .bcdVersion = __constant_cpu_to_le16(0x0100), - .bGUID = { - 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, - 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, - }, -}; - -/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we - * can't really use its struct. All we do here is say that we're using - * the submode of "SAFE" which directly matches the CDC Subset. - */ -static const u8 mdlm_detail_desc[] = { - 6, - USB_DT_CS_INTERFACE, - USB_CDC_MDLM_DETAIL_TYPE, - - 0, /* "SAFE" */ - 0, /* network control capabilities (none) */ - 0, /* network data capabilities ("raw" encapsulation) */ -}; - -#endif - -static const struct usb_cdc_ether_desc ether_desc = { - .bLength = sizeof ether_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, - - /* this descriptor actually adds value, surprise! */ - .iMACAddress = STRING_ETHADDR, - .bmEthernetStatistics = __constant_cpu_to_le32 (0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16 (ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16 (0), - .bNumberPowerFilters = 0, -}; - - -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - -/* include the status endpoint if we can, even where it's optional. - * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one - * packet, to simplify cancellation; and a big transfer interval, to - * waste less bandwidth. - * - * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even - * if they ignore the connect/disconnect notifications that real aether - * can provide. more advanced cdc configurations might want to support - * encapsulated commands (vendor-specific, using control-OUT). - * - * RNDIS requires the status endpoint, since it uses that encapsulation - * mechanism for its funky RPC scheme. - */ - -#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ -#define STATUS_BYTECOUNT 16 /* 8 byte header + data */ - -static struct usb_endpoint_descriptor -fs_status_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT), - .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, -}; -#endif - -#ifdef DEV_CONFIG_CDC - -/* the default data interface has no endpoints ... */ - -static const struct usb_interface_descriptor -data_nop_intf = { - .bLength = sizeof data_nop_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, -}; - -/* ... but the "real" data interface has two bulk endpoints */ - -static const struct usb_interface_descriptor -data_intf = { - .bLength = sizeof data_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 1, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = STRING_DATA, -}; - -#endif - -#ifdef CONFIG_USB_ETH_RNDIS - -/* RNDIS doesn't activate by changing to the "real" altsetting */ - -static const struct usb_interface_descriptor -rndis_data_intf = { - .bLength = sizeof rndis_data_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = STRING_DATA, -}; - -#endif - -#ifdef DEV_CONFIG_SUBSET - -/* - * "Simple" CDC-subset option is a simple vendor-neutral model that most - * full speed controllers can handle: one interface, two bulk endpoints. - * - * To assist host side drivers, we fancy it up a bit, and add descriptors - * so some host side drivers will understand it as a "SAFE" variant. - */ - -static const struct usb_interface_descriptor -subset_data_intf = { - .bLength = sizeof subset_data_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, - .bInterfaceProtocol = 0, - .iInterface = STRING_DATA, -}; - -#endif /* SUBSET */ - - -static struct usb_endpoint_descriptor -fs_source_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_endpoint_descriptor -fs_sink_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, }; -static const struct usb_descriptor_header *fs_eth_function [11] = { +static const struct usb_descriptor_header *otg_desc[] = { (struct usb_descriptor_header *) &otg_descriptor, -#ifdef DEV_CONFIG_CDC - /* "cdc" mode descriptors */ - (struct usb_descriptor_header *) &control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) ðer_desc, - /* NOTE: status endpoint may need to be removed */ - (struct usb_descriptor_header *) &fs_status_desc, - /* data interface, with altsetting */ - (struct usb_descriptor_header *) &data_nop_intf, - (struct usb_descriptor_header *) &data_intf, - (struct usb_descriptor_header *) &fs_source_desc, - (struct usb_descriptor_header *) &fs_sink_desc, NULL, -#endif /* DEV_CONFIG_CDC */ }; -static inline void __init fs_subset_descriptors(void) -{ -#ifdef DEV_CONFIG_SUBSET - /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ - fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; - fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; - fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; - fs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; - fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc; - fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc; - fs_eth_function[8] = NULL; -#else - fs_eth_function[1] = NULL; -#endif -} -#ifdef CONFIG_USB_ETH_RNDIS -static const struct usb_descriptor_header *fs_rndis_function [] = { - (struct usb_descriptor_header *) &otg_descriptor, - /* control interface matches ACM, not Ethernet */ - (struct usb_descriptor_header *) &rndis_control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &call_mgmt_descriptor, - (struct usb_descriptor_header *) &acm_descriptor, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) &fs_status_desc, - /* data interface has no altsetting */ - (struct usb_descriptor_header *) &rndis_data_intf, - (struct usb_descriptor_header *) &fs_source_desc, - (struct usb_descriptor_header *) &fs_sink_desc, - NULL, -}; -#endif - -/* - * usb 2.0 devices need to expose both high speed and full speed - * descriptors, unless they only run at full speed. - */ - -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) -static struct usb_endpoint_descriptor -hs_status_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT), - .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, -}; -#endif /* DEV_CONFIG_CDC */ - -static struct usb_endpoint_descriptor -hs_source_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16 (512), -}; - -static struct usb_endpoint_descriptor -hs_sink_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16 (512), -}; +/* string IDs are assigned dynamically */ -static struct usb_qualifier_descriptor -dev_qualifier = { - .bLength = sizeof dev_qualifier, - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 - .bcdUSB = __constant_cpu_to_le16 (0x0200), - .bDeviceClass = USB_CLASS_COMM, +static char manufacturer[50]; - .bNumConfigurations = 1, +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer, + [STRING_PRODUCT_IDX].s = PREFIX DRIVER_DESC, + { } /* end of list */ }; -static const struct usb_descriptor_header *hs_eth_function [11] = { - (struct usb_descriptor_header *) &otg_descriptor, -#ifdef DEV_CONFIG_CDC - /* "cdc" mode descriptors */ - (struct usb_descriptor_header *) &control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) ðer_desc, - /* NOTE: status endpoint may need to be removed */ - (struct usb_descriptor_header *) &hs_status_desc, - /* data interface, with altsetting */ - (struct usb_descriptor_header *) &data_nop_intf, - (struct usb_descriptor_header *) &data_intf, - (struct usb_descriptor_header *) &hs_source_desc, - (struct usb_descriptor_header *) &hs_sink_desc, - NULL, -#endif /* DEV_CONFIG_CDC */ +static struct usb_gadget_strings stringtab_dev = { + .language = 0x0409, /* en-us */ + .strings = strings_dev, }; -static inline void __init hs_subset_descriptors(void) -{ -#ifdef DEV_CONFIG_SUBSET - /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ - hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; - hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; - hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; - hs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; - hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc; - hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc; - hs_eth_function[8] = NULL; -#else - hs_eth_function[1] = NULL; -#endif -} - -#ifdef CONFIG_USB_ETH_RNDIS -static const struct usb_descriptor_header *hs_rndis_function [] = { - (struct usb_descriptor_header *) &otg_descriptor, - /* control interface matches ACM, not Ethernet */ - (struct usb_descriptor_header *) &rndis_control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &call_mgmt_descriptor, - (struct usb_descriptor_header *) &acm_descriptor, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) &hs_status_desc, - /* data interface has no altsetting */ - (struct usb_descriptor_header *) &rndis_data_intf, - (struct usb_descriptor_header *) &hs_source_desc, - (struct usb_descriptor_header *) &hs_sink_desc, +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, NULL, }; -#endif - - -/* maxpacket and other transfer characteristics vary by speed. */ -static inline struct usb_endpoint_descriptor * -ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, - struct usb_endpoint_descriptor *fs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} +static u8 hostaddr[ETH_ALEN]; /*-------------------------------------------------------------------------*/ -/* descriptors that are built on-demand */ - -static char manufacturer [50]; -static char product_desc [40] = DRIVER_DESC; -static char serial_number [20]; - -/* address that the host will use ... usually assigned at random */ -static char ethaddr [2 * ETH_ALEN + 1]; - -/* static strings, in UTF-8 */ -static struct usb_string strings [] = { - { STRING_MANUFACTURER, manufacturer, }, - { STRING_PRODUCT, product_desc, }, - { STRING_SERIALNUMBER, serial_number, }, - { STRING_DATA, "Ethernet Data", }, - { STRING_ETHADDR, ethaddr, }, -#ifdef DEV_CONFIG_CDC - { STRING_CDC, "CDC Ethernet", }, - { STRING_CONTROL, "CDC Communications Control", }, -#endif -#ifdef DEV_CONFIG_SUBSET - { STRING_SUBSET, "CDC Ethernet Subset", }, -#endif -#ifdef CONFIG_USB_ETH_RNDIS - { STRING_RNDIS, "RNDIS", }, - { STRING_RNDIS_CONTROL, "RNDIS Communications Control", }, -#endif - { } /* end of list */ -}; - -static struct usb_gadget_strings stringtab = { - .language = 0x0409, /* en-us */ - .strings = strings, -}; - /* - * one config, two interfaces: control, data. - * complications: class descriptors, and an altsetting. - */ -static int -config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg) -{ - int len; - const struct usb_config_descriptor *config; - const struct usb_descriptor_header **function; - int hs = 0; - - if (gadget_is_dualspeed(g)) { - hs = (g->speed == USB_SPEED_HIGH); - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - } -#define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function) - - if (index >= device_desc.bNumConfigurations) - return -EINVAL; - -#ifdef CONFIG_USB_ETH_RNDIS - /* list the RNDIS config first, to make Microsoft's drivers - * happy. DOCSIS 1.0 needs this too. - */ - if (device_desc.bNumConfigurations == 2 && index == 0) { - config = &rndis_config; - function = which_fn (rndis); - } else -#endif - { - config = ð_config; - function = which_fn (eth); - } - - /* for now, don't advertise srp-only devices */ - if (!is_otg) - function++; - - len = usb_gadget_config_buf (config, buf, USB_BUFSIZ, function); - if (len < 0) - return len; - ((struct usb_config_descriptor *) buf)->bDescriptorType = type; - return len; -} - -/*-------------------------------------------------------------------------*/ - -static void eth_start (struct eth_dev *dev, gfp_t gfp_flags); -static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags); - -static int -set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) -{ - int result = 0; - struct usb_gadget *gadget = dev->gadget; - -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - /* status endpoint used for RNDIS and (optionally) CDC */ - if (!subset_active(dev) && dev->status_ep) { - dev->status = ep_desc (gadget, &hs_status_desc, - &fs_status_desc); - dev->status_ep->driver_data = dev; - - result = usb_ep_enable (dev->status_ep, dev->status); - if (result != 0) { - DEBUG (dev, "enable %s --> %d\n", - dev->status_ep->name, result); - goto done; - } - } -#endif - - dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc); - dev->in_ep->driver_data = dev; - - dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc); - dev->out_ep->driver_data = dev; - - /* With CDC, the host isn't allowed to use these two data - * endpoints in the default altsetting for the interface. - * so we don't activate them yet. Reset from SET_INTERFACE. - * - * Strictly speaking RNDIS should work the same: activation is - * a side effect of setting a packet filter. Deactivation is - * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG. - */ - if (!cdc_active(dev)) { - result = usb_ep_enable (dev->in_ep, dev->in); - if (result != 0) { - DEBUG(dev, "enable %s --> %d\n", - dev->in_ep->name, result); - goto done; - } - - result = usb_ep_enable (dev->out_ep, dev->out); - if (result != 0) { - DEBUG (dev, "enable %s --> %d\n", - dev->out_ep->name, result); - goto done; - } - } - -done: - if (result == 0) - result = alloc_requests (dev, qlen (gadget), gfp_flags); - - /* on error, disable any endpoints */ - if (result < 0) { - if (!subset_active(dev) && dev->status_ep) - (void) usb_ep_disable (dev->status_ep); - dev->status = NULL; - (void) usb_ep_disable (dev->in_ep); - (void) usb_ep_disable (dev->out_ep); - dev->in = NULL; - dev->out = NULL; - } - - /* activate non-CDC configs right away - * this isn't strictly according to the RNDIS spec - */ - else if (!cdc_active (dev)) { - netif_carrier_on (dev->net); - if (netif_running (dev->net)) { - spin_unlock (&dev->lock); - eth_start (dev, GFP_ATOMIC); - spin_lock (&dev->lock); - } - } - - if (result == 0) - DEBUG (dev, "qlen %d\n", qlen (gadget)); - - /* caller is responsible for cleanup on error */ - return result; -} - -static void eth_reset_config (struct eth_dev *dev) -{ - struct usb_request *req; - - if (dev->config == 0) - return; - - DEBUG (dev, "%s\n", __func__); - - netif_stop_queue (dev->net); - netif_carrier_off (dev->net); - rndis_uninit(dev->rndis_config); - - /* disable endpoints, forcing (synchronous) completion of - * pending i/o. then free the requests. - */ - if (dev->in) { - usb_ep_disable (dev->in_ep); - spin_lock(&dev->req_lock); - while (likely (!list_empty (&dev->tx_reqs))) { - req = container_of (dev->tx_reqs.next, - struct usb_request, list); - list_del (&req->list); - - spin_unlock(&dev->req_lock); - usb_ep_free_request (dev->in_ep, req); - spin_lock(&dev->req_lock); - } - spin_unlock(&dev->req_lock); - } - if (dev->out) { - usb_ep_disable (dev->out_ep); - spin_lock(&dev->req_lock); - while (likely (!list_empty (&dev->rx_reqs))) { - req = container_of (dev->rx_reqs.next, - struct usb_request, list); - list_del (&req->list); - - spin_unlock(&dev->req_lock); - usb_ep_free_request (dev->out_ep, req); - spin_lock(&dev->req_lock); - } - spin_unlock(&dev->req_lock); - } - - if (dev->status) { - usb_ep_disable (dev->status_ep); - } - dev->rndis = 0; - dev->cdc_filter = 0; - dev->config = 0; -} - -/* change our operational config. must agree with the code - * that returns config descriptors, and altsetting code. + * We may not have an RNDIS configuration, but if we do it needs to be + * the first one present. That's to make Microsoft's drivers happy, + * and to follow DOCSIS 1.0 (cable modem standard). */ -static int -eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags) +static int __init rndis_do_config(struct usb_configuration *c) { - int result = 0; - struct usb_gadget *gadget = dev->gadget; - - if (gadget_is_sa1100 (gadget) - && dev->config - && atomic_read (&dev->tx_qlen) != 0) { - /* tx fifo is full, but we can't clear it...*/ - INFO (dev, "can't change configurations\n"); - return -ESPIPE; - } - eth_reset_config (dev); - - switch (number) { - case DEV_CONFIG_VALUE: - result = set_ether_config (dev, gfp_flags); - break; -#ifdef CONFIG_USB_ETH_RNDIS - case DEV_RNDIS_CONFIG_VALUE: - dev->rndis = 1; - result = set_ether_config (dev, gfp_flags); - break; -#endif - default: - result = -EINVAL; - /* FALL THROUGH */ - case 0: - break; - } - - if (result) { - if (number) - eth_reset_config (dev); - usb_gadget_vbus_draw(dev->gadget, - gadget_is_otg(dev->gadget) ? 8 : 100); - } else { - char *speed; - unsigned power; - - power = 2 * eth_config.bMaxPower; - usb_gadget_vbus_draw(dev->gadget, power); + /* FIXME alloc iConfiguration string, set it in c->strings */ - switch (gadget->speed) { - case USB_SPEED_FULL: speed = "full"; break; -#ifdef CONFIG_USB_GADGET_DUALSPEED - case USB_SPEED_HIGH: speed = "high"; break; -#endif - default: speed = "?"; break; - } - - dev->config = number; - INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n", - speed, number, power, driver_desc, - rndis_active(dev) - ? "RNDIS" - : (cdc_active(dev) - ? "CDC Ethernet" - : "CDC Ethernet Subset")); + if (gadget_is_otg(c->cdev->gadget)) { + c->descriptors = otg_desc; + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - return result; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEV_CONFIG_CDC -/* The interrupt endpoint is used in CDC networking models (Ethernet, ATM) - * only to notify the host about link status changes (which we support) or - * report completion of some encapsulated command (as used in RNDIS). Since - * we want this CDC Ethernet code to be vendor-neutral, we don't use that - * command mechanism; and only one status request is ever queued. - */ - -static void eth_status_complete (struct usb_ep *ep, struct usb_request *req) -{ - struct usb_cdc_notification *event = req->buf; - int value = req->status; - struct eth_dev *dev = ep->driver_data; - - /* issue the second notification if host reads the first */ - if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION - && value == 0) { - __le32 *data = req->buf + sizeof *event; - - event->bmRequestType = 0xA1; - event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE; - event->wValue = __constant_cpu_to_le16 (0); - event->wIndex = __constant_cpu_to_le16 (1); - event->wLength = __constant_cpu_to_le16 (8); - - /* SPEED_CHANGE data is up/down speeds in bits/sec */ - data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget)); - - req->length = STATUS_BYTECOUNT; - value = usb_ep_queue (ep, req, GFP_ATOMIC); - DEBUG (dev, "send SPEED_CHANGE --> %d\n", value); - if (value == 0) - return; - } else if (value != -ECONNRESET) - DEBUG (dev, "event %02x --> %d\n", - event->bNotificationType, value); - req->context = NULL; + return rndis_bind_config(c, hostaddr); } -static void issue_start_status (struct eth_dev *dev) -{ - struct usb_request *req = dev->stat_req; - struct usb_cdc_notification *event; - int value; - - DEBUG (dev, "%s, flush old status first\n", __func__); - - /* flush old status - * - * FIXME ugly idiom, maybe we'd be better with just - * a "cancel the whole queue" primitive since any - * unlink-one primitive has way too many error modes. - * here, we "know" toggle is already clear... - * - * FIXME iff req->context != null just dequeue it - */ - usb_ep_disable (dev->status_ep); - usb_ep_enable (dev->status_ep, dev->status); - - /* 3.8.1 says to issue first NETWORK_CONNECTION, then - * a SPEED_CHANGE. could be useful in some configs. - */ - event = req->buf; - event->bmRequestType = 0xA1; - event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION; - event->wValue = __constant_cpu_to_le16 (1); /* connected */ - event->wIndex = __constant_cpu_to_le16 (1); - event->wLength = 0; - - req->length = sizeof *event; - req->complete = eth_status_complete; - req->context = dev; - - value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC); - if (value < 0) - DEBUG (dev, "status buf queue --> %d\n", value); -} - -#endif +static struct usb_configuration rndis_config_driver = { + .label = "RNDIS", + .bind = rndis_do_config, + .bConfigurationValue = 2, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* 2 mA, minimal */ +}; /*-------------------------------------------------------------------------*/ -static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - DEBUG ((struct eth_dev *) ep->driver_data, - "setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - -#ifdef CONFIG_USB_ETH_RNDIS - -static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - DEBUG ((struct eth_dev *) ep->driver_data, - "rndis response complete --> %d, %d/%d\n", - req->status, req->actual, req->length); - - /* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */ -} - -static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req) -{ - struct eth_dev *dev = ep->driver_data; - int status; - - /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ - spin_lock(&dev->lock); - status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf); - if (status < 0) - ERROR(dev, "%s: rndis parse error %d\n", __func__, status); - spin_unlock(&dev->lock); -} - -#endif /* RNDIS */ - /* - * The setup() callback implements all the ep0 functionality that's not - * handled lower down. CDC has a number of less-common features: - * - * - two interfaces: control, and ethernet data - * - Ethernet data interface has two altsettings: default, and active - * - class-specific descriptors for the control interface - * - class-specific control requests + * We _always_ have an ECM or CDC Subset configuration. */ -static int -eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) +static int __init eth_do_config(struct usb_configuration *c) { - struct eth_dev *dev = get_gadget_data (gadget); - struct usb_request *req = dev->req; - int value = -EOPNOTSUPP; - u16 wIndex = le16_to_cpu(ctrl->wIndex); - u16 wValue = le16_to_cpu(ctrl->wValue); - u16 wLength = le16_to_cpu(ctrl->wLength); - - /* descriptors just go into the pre-allocated ep0 buffer, - * while config change events may enable network traffic. - */ - req->complete = eth_setup_complete; - switch (ctrl->bRequest) { - - case USB_REQ_GET_DESCRIPTOR: - if (ctrl->bRequestType != USB_DIR_IN) - break; - switch (wValue >> 8) { - - case USB_DT_DEVICE: - value = min (wLength, (u16) sizeof device_desc); - memcpy (req->buf, &device_desc, value); - break; - case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) - break; - value = min (wLength, (u16) sizeof dev_qualifier); - memcpy (req->buf, &dev_qualifier, value); - break; - - case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) - break; - // FALLTHROUGH - case USB_DT_CONFIG: - value = config_buf(gadget, req->buf, - wValue >> 8, - wValue & 0xff, - gadget_is_otg(gadget)); - if (value >= 0) - value = min (wLength, (u16) value); - break; - - case USB_DT_STRING: - value = usb_gadget_get_string (&stringtab, - wValue & 0xff, req->buf); - if (value >= 0) - value = min (wLength, (u16) value); - break; - } - break; - - case USB_REQ_SET_CONFIGURATION: - if (ctrl->bRequestType != 0) - break; - if (gadget->a_hnp_support) - DEBUG (dev, "HNP available\n"); - else if (gadget->a_alt_hnp_support) - DEBUG (dev, "HNP needs a different root port\n"); - spin_lock (&dev->lock); - value = eth_set_config (dev, wValue, GFP_ATOMIC); - spin_unlock (&dev->lock); - break; - case USB_REQ_GET_CONFIGURATION: - if (ctrl->bRequestType != USB_DIR_IN) - break; - *(u8 *)req->buf = dev->config; - value = min (wLength, (u16) 1); - break; - - case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE - || !dev->config - || wIndex > 1) - break; - if (!cdc_active(dev) && wIndex != 0) - break; - spin_lock (&dev->lock); - - /* PXA hardware partially handles SET_INTERFACE; - * we need to kluge around that interference. - */ - if (gadget_is_pxa (gadget)) { - value = eth_set_config (dev, DEV_CONFIG_VALUE, - GFP_ATOMIC); - goto done_set_intf; - } - -#ifdef DEV_CONFIG_CDC - switch (wIndex) { - case 0: /* control/master intf */ - if (wValue != 0) - break; - if (dev->status) { - usb_ep_disable (dev->status_ep); - usb_ep_enable (dev->status_ep, dev->status); - } - value = 0; - break; - case 1: /* data intf */ - if (wValue > 1) - break; - usb_ep_disable (dev->in_ep); - usb_ep_disable (dev->out_ep); - - /* CDC requires the data transfers not be done from - * the default interface setting ... also, setting - * the non-default interface resets filters etc. - */ - if (wValue == 1) { - if (!cdc_active (dev)) - break; - usb_ep_enable (dev->in_ep, dev->in); - usb_ep_enable (dev->out_ep, dev->out); - dev->cdc_filter = DEFAULT_FILTER; - netif_carrier_on (dev->net); - if (dev->status) - issue_start_status (dev); - if (netif_running (dev->net)) { - spin_unlock (&dev->lock); - eth_start (dev, GFP_ATOMIC); - spin_lock (&dev->lock); - } - } else { - netif_stop_queue (dev->net); - netif_carrier_off (dev->net); - } - value = 0; - break; - } -#else - /* FIXME this is wrong, as is the assumption that - * all non-PXA hardware talks real CDC ... - */ - dev_warn (&gadget->dev, "set_interface ignored!\n"); -#endif /* DEV_CONFIG_CDC */ - -done_set_intf: - spin_unlock (&dev->lock); - break; - case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE) - || !dev->config - || wIndex > 1) - break; - if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0) - break; - - /* for CDC, iff carrier is on, data interface is active. */ - if (rndis_active(dev) || wIndex != 1) - *(u8 *)req->buf = 0; - else - *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0; - value = min (wLength, (u16) 1); - break; - -#ifdef DEV_CONFIG_CDC - case USB_CDC_SET_ETHERNET_PACKET_FILTER: - /* see 6.2.30: no data, wIndex = interface, - * wValue = packet filter bitmap - */ - if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) - || !cdc_active(dev) - || wLength != 0 - || wIndex > 1) - break; - DEBUG (dev, "packet filter %02x\n", wValue); - dev->cdc_filter = wValue; - value = 0; - break; - - /* and potentially: - * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS: - * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER: - * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER: - * case USB_CDC_GET_ETHERNET_STATISTIC: - */ - -#endif /* DEV_CONFIG_CDC */ + /* FIXME alloc iConfiguration string, set it in c->strings */ -#ifdef CONFIG_USB_ETH_RNDIS - /* RNDIS uses the CDC command encapsulation mechanism to implement - * an RPC scheme, with much getting/setting of attributes by OID. - */ - case USB_CDC_SEND_ENCAPSULATED_COMMAND: - if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) - || !rndis_active(dev) - || wLength > USB_BUFSIZ - || wValue - || rndis_control_intf.bInterfaceNumber - != wIndex) - break; - /* read the request, then process it */ - value = wLength; - req->complete = rndis_command_complete; - /* later, rndis_control_ack () sends a notification */ - break; - - case USB_CDC_GET_ENCAPSULATED_RESPONSE: - if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) - == ctrl->bRequestType - && rndis_active(dev) - // && wLength >= 0x0400 - && !wValue - && rndis_control_intf.bInterfaceNumber - == wIndex) { - u8 *buf; - u32 n; - - /* return the result */ - buf = rndis_get_next_response(dev->rndis_config, &n); - if (buf) { - memcpy(req->buf, buf, n); - req->complete = rndis_response_complete; - rndis_free_response(dev->rndis_config, buf); - value = n; - } - /* else stalls ... spec says to avoid that */ - } - break; -#endif /* RNDIS */ - - default: - VDEBUG (dev, - "unknown control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - wValue, wIndex, wLength); + if (gadget_is_otg(c->cdev->gadget)) { + c->descriptors = otg_desc; + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - /* respond with data transfer before status phase? */ - if (value >= 0) { - req->length = value; - req->zero = value < wLength - && (value % gadget->ep0->maxpacket) == 0; - value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); - if (value < 0) { - DEBUG (dev, "ep_queue --> %d\n", value); - req->status = 0; - eth_setup_complete (gadget->ep0, req); - } - } - - /* host either stalls (value < 0) or reports success */ - return value; -} - -static void -eth_disconnect (struct usb_gadget *gadget) -{ - struct eth_dev *dev = get_gadget_data (gadget); - unsigned long flags; - - spin_lock_irqsave (&dev->lock, flags); - netif_stop_queue (dev->net); - netif_carrier_off (dev->net); - eth_reset_config (dev); - spin_unlock_irqrestore (&dev->lock, flags); - - /* FIXME RNDIS should enter RNDIS_UNINITIALIZED */ - - /* next we may get setup() calls to enumerate new connections; - * or an unbind() during shutdown (including removing module). - */ -} - -/*-------------------------------------------------------------------------*/ - -/* NETWORK DRIVER HOOKUP (to the layer above this driver) */ - -static int eth_change_mtu (struct net_device *net, int new_mtu) -{ - struct eth_dev *dev = netdev_priv(net); - - if (dev->rndis) - return -EBUSY; - - if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN) - return -ERANGE; - /* no zero-length packet read wanted after mtu-sized packets */ - if (((new_mtu + sizeof (struct ethhdr)) % dev->in_ep->maxpacket) == 0) - return -EDOM; - net->mtu = new_mtu; - return 0; -} - -static struct net_device_stats *eth_get_stats (struct net_device *net) -{ - return &((struct eth_dev *)netdev_priv(net))->stats; -} - -static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) -{ - struct eth_dev *dev = netdev_priv(net); - strlcpy(p->driver, shortname, sizeof p->driver); - strlcpy(p->version, DRIVER_VERSION, sizeof p->version); - strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version); - strlcpy (p->bus_info, dev->gadget->dev.bus_id, sizeof p->bus_info); -} - -static u32 eth_get_link(struct net_device *net) -{ - struct eth_dev *dev = netdev_priv(net); - return dev->gadget->speed != USB_SPEED_UNKNOWN; -} - -static struct ethtool_ops ops = { - .get_drvinfo = eth_get_drvinfo, - .get_link = eth_get_link -}; - -static void defer_kevent (struct eth_dev *dev, int flag) -{ - if (test_and_set_bit (flag, &dev->todo)) - return; - if (!schedule_work (&dev->work)) - ERROR (dev, "kevent %d may have been dropped\n", flag); + if (can_support_ecm(c->cdev->gadget)) + return ecm_bind_config(c, hostaddr); else - DEBUG (dev, "kevent %d scheduled\n", flag); -} - -static void rx_complete (struct usb_ep *ep, struct usb_request *req); - -static int -rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) -{ - struct sk_buff *skb; - int retval = -ENOMEM; - size_t size; - - /* Padding up to RX_EXTRA handles minor disagreements with host. - * Normally we use the USB "terminate on short read" convention; - * so allow up to (N*maxpacket), since that memory is normally - * already allocated. Some hardware doesn't deal well with short - * reads (e.g. DMA must be N*maxpacket), so for now don't trim a - * byte off the end (to force hardware errors on overflow). - * - * RNDIS uses internal framing, and explicitly allows senders to - * pad to end-of-packet. That's potentially nice for speed, - * but means receivers can't recover synch on their own. - */ - size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA); - size += dev->out_ep->maxpacket - 1; - if (rndis_active(dev)) - size += sizeof (struct rndis_packet_msg_type); - size -= size % dev->out_ep->maxpacket; - - skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); - if (skb == NULL) { - DEBUG (dev, "no rx skb\n"); - goto enomem; - } - - /* Some platforms perform better when IP packets are aligned, - * but on at least one, checksumming fails otherwise. Note: - * RNDIS headers involve variable numbers of LE32 values. - */ - skb_reserve(skb, NET_IP_ALIGN); - - req->buf = skb->data; - req->length = size; - req->complete = rx_complete; - req->context = skb; - - retval = usb_ep_queue (dev->out_ep, req, gfp_flags); - if (retval == -ENOMEM) -enomem: - defer_kevent (dev, WORK_RX_MEMORY); - if (retval) { - DEBUG (dev, "rx submit --> %d\n", retval); - if (skb) - dev_kfree_skb_any(skb); - spin_lock(&dev->req_lock); - list_add (&req->list, &dev->rx_reqs); - spin_unlock(&dev->req_lock); - } - return retval; -} - -static void rx_complete (struct usb_ep *ep, struct usb_request *req) -{ - struct sk_buff *skb = req->context; - struct eth_dev *dev = ep->driver_data; - int status = req->status; - - switch (status) { - - /* normal completion */ - case 0: - skb_put (skb, req->actual); - /* we know MaxPacketsPerTransfer == 1 here */ - if (rndis_active(dev)) - status = rndis_rm_hdr (skb); - if (status < 0 - || ETH_HLEN > skb->len - || skb->len > ETH_FRAME_LEN) { - dev->stats.rx_errors++; - dev->stats.rx_length_errors++; - DEBUG (dev, "rx length %d\n", skb->len); - break; - } - - skb->protocol = eth_type_trans (skb, dev->net); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - - /* no buffer copies needed, unless hardware can't - * use skb buffers. - */ - status = netif_rx (skb); - skb = NULL; - break; - - /* software-driven interface shutdown */ - case -ECONNRESET: // unlink - case -ESHUTDOWN: // disconnect etc - VDEBUG (dev, "rx shutdown, code %d\n", status); - goto quiesce; - - /* for hardware automagic (such as pxa) */ - case -ECONNABORTED: // endpoint reset - DEBUG (dev, "rx %s reset\n", ep->name); - defer_kevent (dev, WORK_RX_MEMORY); -quiesce: - dev_kfree_skb_any (skb); - goto clean; - - /* data overrun */ - case -EOVERFLOW: - dev->stats.rx_over_errors++; - // FALLTHROUGH - - default: - dev->stats.rx_errors++; - DEBUG (dev, "rx status %d\n", status); - break; - } - - if (skb) - dev_kfree_skb_any (skb); - if (!netif_running (dev->net)) { -clean: - spin_lock(&dev->req_lock); - list_add (&req->list, &dev->rx_reqs); - spin_unlock(&dev->req_lock); - req = NULL; - } - if (req) - rx_submit (dev, req, GFP_ATOMIC); -} - -static int prealloc (struct list_head *list, struct usb_ep *ep, - unsigned n, gfp_t gfp_flags) -{ - unsigned i; - struct usb_request *req; - - if (!n) - return -ENOMEM; - - /* queue/recycle up to N requests */ - i = n; - list_for_each_entry (req, list, list) { - if (i-- == 0) - goto extra; - } - while (i--) { - req = usb_ep_alloc_request (ep, gfp_flags); - if (!req) - return list_empty (list) ? -ENOMEM : 0; - list_add (&req->list, list); - } - return 0; - -extra: - /* free extras */ - for (;;) { - struct list_head *next; - - next = req->list.next; - list_del (&req->list); - usb_ep_free_request (ep, req); - - if (next == list) - break; - - req = container_of (next, struct usb_request, list); - } - return 0; -} - -static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags) -{ - int status; - - spin_lock(&dev->req_lock); - status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags); - if (status < 0) - goto fail; - status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags); - if (status < 0) - goto fail; - goto done; -fail: - DEBUG (dev, "can't alloc requests\n"); -done: - spin_unlock(&dev->req_lock); - return status; -} - -static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags) -{ - struct usb_request *req; - unsigned long flags; - - /* fill unused rxq slots with some skb */ - spin_lock_irqsave(&dev->req_lock, flags); - while (!list_empty (&dev->rx_reqs)) { - req = container_of (dev->rx_reqs.next, - struct usb_request, list); - list_del_init (&req->list); - spin_unlock_irqrestore(&dev->req_lock, flags); - - if (rx_submit (dev, req, gfp_flags) < 0) { - defer_kevent (dev, WORK_RX_MEMORY); - return; - } - - spin_lock_irqsave(&dev->req_lock, flags); - } - spin_unlock_irqrestore(&dev->req_lock, flags); -} - -static void eth_work (struct work_struct *work) -{ - struct eth_dev *dev = container_of(work, struct eth_dev, work); - - if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) { - if (netif_running (dev->net)) - rx_fill (dev, GFP_KERNEL); - } - - if (dev->todo) - DEBUG (dev, "work done, flags = 0x%lx\n", dev->todo); -} - -static void tx_complete (struct usb_ep *ep, struct usb_request *req) -{ - struct sk_buff *skb = req->context; - struct eth_dev *dev = ep->driver_data; - - switch (req->status) { - default: - dev->stats.tx_errors++; - VDEBUG (dev, "tx err %d\n", req->status); - /* FALLTHROUGH */ - case -ECONNRESET: // unlink - case -ESHUTDOWN: // disconnect etc - break; - case 0: - dev->stats.tx_bytes += skb->len; - } - dev->stats.tx_packets++; - - spin_lock(&dev->req_lock); - list_add (&req->list, &dev->tx_reqs); - spin_unlock(&dev->req_lock); - dev_kfree_skb_any (skb); - - atomic_dec (&dev->tx_qlen); - if (netif_carrier_ok (dev->net)) - netif_wake_queue (dev->net); -} - -static inline int eth_is_promisc (struct eth_dev *dev) -{ - /* no filters for the CDC subset; always promisc */ - if (subset_active (dev)) - return 1; - return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS; -} - -static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) -{ - struct eth_dev *dev = netdev_priv(net); - int length = skb->len; - int retval; - struct usb_request *req = NULL; - unsigned long flags; - - /* apply outgoing CDC or RNDIS filters */ - if (!eth_is_promisc (dev)) { - u8 *dest = skb->data; - - if (is_multicast_ether_addr(dest)) { - u16 type; - - /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host - * SET_ETHERNET_MULTICAST_FILTERS requests - */ - if (is_broadcast_ether_addr(dest)) - type = USB_CDC_PACKET_TYPE_BROADCAST; - else - type = USB_CDC_PACKET_TYPE_ALL_MULTICAST; - if (!(dev->cdc_filter & type)) { - dev_kfree_skb_any (skb); - return 0; - } - } - /* ignores USB_CDC_PACKET_TYPE_DIRECTED */ - } - - spin_lock_irqsave(&dev->req_lock, flags); - /* - * this freelist can be empty if an interrupt triggered disconnect() - * and reconfigured the gadget (shutting down this queue) after the - * network stack decided to xmit but before we got the spinlock. - */ - if (list_empty(&dev->tx_reqs)) { - spin_unlock_irqrestore(&dev->req_lock, flags); - return 1; - } - - req = container_of (dev->tx_reqs.next, struct usb_request, list); - list_del (&req->list); - - /* temporarily stop TX queue when the freelist empties */ - if (list_empty (&dev->tx_reqs)) - netif_stop_queue (net); - spin_unlock_irqrestore(&dev->req_lock, flags); - - /* no buffer copies needed, unless the network stack did it - * or the hardware can't use skb buffers. - * or there's not enough space for any RNDIS headers we need - */ - if (rndis_active(dev)) { - struct sk_buff *skb_rndis; - - skb_rndis = skb_realloc_headroom (skb, - sizeof (struct rndis_packet_msg_type)); - if (!skb_rndis) - goto drop; - - dev_kfree_skb_any (skb); - skb = skb_rndis; - rndis_add_hdr (skb); - length = skb->len; - } - req->buf = skb->data; - req->context = skb; - req->complete = tx_complete; - - /* use zlp framing on tx for strict CDC-Ether conformance, - * though any robust network rx path ignores extra padding. - * and some hardware doesn't like to write zlps. - */ - req->zero = 1; - if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0) - length++; - - req->length = length; - - /* throttle highspeed IRQ rate back slightly */ - if (gadget_is_dualspeed(dev->gadget)) - req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) - ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) - : 0; - - retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC); - switch (retval) { - default: - DEBUG (dev, "tx queue err %d\n", retval); - break; - case 0: - net->trans_start = jiffies; - atomic_inc (&dev->tx_qlen); - } - - if (retval) { -drop: - dev->stats.tx_dropped++; - dev_kfree_skb_any (skb); - spin_lock_irqsave(&dev->req_lock, flags); - if (list_empty (&dev->tx_reqs)) - netif_start_queue (net); - list_add (&req->list, &dev->tx_reqs); - spin_unlock_irqrestore(&dev->req_lock, flags); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_ETH_RNDIS - -/* The interrupt endpoint is used in RNDIS to notify the host when messages - * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT - * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even - * REMOTE_NDIS_KEEPALIVE_MSG. - * - * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and - * normally just one notification will be queued. - */ - -static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t); -static void eth_req_free (struct usb_ep *ep, struct usb_request *req); - -static void -rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) -{ - struct eth_dev *dev = ep->driver_data; - - if (req->status || req->actual != req->length) - DEBUG (dev, - "rndis control ack complete --> %d, %d/%d\n", - req->status, req->actual, req->length); - req->context = NULL; - - if (req != dev->stat_req) - eth_req_free(ep, req); -} - -static int rndis_control_ack (struct net_device *net) -{ - struct eth_dev *dev = netdev_priv(net); - int length; - struct usb_request *resp = dev->stat_req; - - /* in case RNDIS calls this after disconnect */ - if (!dev->status) { - DEBUG (dev, "status ENODEV\n"); - return -ENODEV; - } - - /* in case queue length > 1 */ - if (resp->context) { - resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC); - if (!resp) - return -ENOMEM; - } - - /* Send RNDIS RESPONSE_AVAILABLE notification; - * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too - */ - resp->length = 8; - resp->complete = rndis_control_ack_complete; - resp->context = dev; - - *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); - *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); - - length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); - if (length < 0) { - resp->status = 0; - rndis_control_ack_complete (dev->status_ep, resp); - } - - return 0; -} - -#else - -#define rndis_control_ack NULL - -#endif /* RNDIS */ - -static void eth_start (struct eth_dev *dev, gfp_t gfp_flags) -{ - DEBUG (dev, "%s\n", __func__); - - /* fill the rx queue */ - rx_fill (dev, gfp_flags); - - /* and open the tx floodgates */ - atomic_set (&dev->tx_qlen, 0); - netif_wake_queue (dev->net); - if (rndis_active(dev)) { - rndis_set_param_medium (dev->rndis_config, - NDIS_MEDIUM_802_3, - BITRATE(dev->gadget)/100); - (void) rndis_signal_connect (dev->rndis_config); - } -} - -static int eth_open (struct net_device *net) -{ - struct eth_dev *dev = netdev_priv(net); - - DEBUG (dev, "%s\n", __func__); - if (netif_carrier_ok (dev->net)) - eth_start (dev, GFP_KERNEL); - return 0; + return geth_bind_config(c, hostaddr); } -static int eth_stop (struct net_device *net) -{ - struct eth_dev *dev = netdev_priv(net); - - VDEBUG (dev, "%s\n", __func__); - netif_stop_queue (net); - - DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", - dev->stats.rx_packets, dev->stats.tx_packets, - dev->stats.rx_errors, dev->stats.tx_errors - ); - - /* ensure there are no more active requests */ - if (dev->config) { - usb_ep_disable (dev->in_ep); - usb_ep_disable (dev->out_ep); - if (netif_carrier_ok (dev->net)) { - DEBUG (dev, "host still using in/out endpoints\n"); - // FIXME idiom may leave toggle wrong here - usb_ep_enable (dev->in_ep, dev->in); - usb_ep_enable (dev->out_ep, dev->out); - } - if (dev->status_ep) { - usb_ep_disable (dev->status_ep); - usb_ep_enable (dev->status_ep, dev->status); - } - } - - if (rndis_active(dev)) { - rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0); - (void) rndis_signal_disconnect (dev->rndis_config); - } - - return 0; -} +static struct usb_configuration eth_config_driver = { + /* .label = f(hardware) */ + .bind = eth_do_config, + .bConfigurationValue = 1, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* 2 mA, minimal */ +}; /*-------------------------------------------------------------------------*/ -static struct usb_request * -eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags) +static int __init eth_bind(struct usb_composite_dev *cdev) { - struct usb_request *req; - - req = usb_ep_alloc_request (ep, gfp_flags); - if (!req) - return NULL; - - req->buf = kmalloc (size, gfp_flags); - if (!req->buf) { - usb_ep_free_request (ep, req); - req = NULL; - } - return req; -} - -static void -eth_req_free (struct usb_ep *ep, struct usb_request *req) -{ - kfree (req->buf); - usb_ep_free_request (ep, req); -} - - -static void /* __init_or_exit */ -eth_unbind (struct usb_gadget *gadget) -{ - struct eth_dev *dev = get_gadget_data (gadget); - - DEBUG (dev, "unbind\n"); - rndis_deregister (dev->rndis_config); - rndis_exit (); - - /* we've already been disconnected ... no i/o is active */ - if (dev->req) { - eth_req_free (gadget->ep0, dev->req); - dev->req = NULL; - } - if (dev->stat_req) { - eth_req_free (dev->status_ep, dev->stat_req); - dev->stat_req = NULL; - } - - unregister_netdev (dev->net); - free_netdev(dev->net); - - /* assuming we used keventd, it must quiesce too */ - flush_scheduled_work (); - set_gadget_data (gadget, NULL); -} - -static u8 __init nibble (unsigned char c) -{ - if (likely (isdigit (c))) - return c - '0'; - c = toupper (c); - if (likely (isxdigit (c))) - return 10 + c - 'A'; - return 0; -} + int gcnum; + struct usb_gadget *gadget = cdev->gadget; + int status; -static int __init get_ether_addr(const char *str, u8 *dev_addr) -{ - if (str) { - unsigned i; + /* set up network link layer */ + status = gether_setup(cdev->gadget, hostaddr); + if (status < 0) + return status; - for (i = 0; i < 6; i++) { - unsigned char num; + /* set up main config label and device descriptor */ + if (can_support_ecm(cdev->gadget)) { + /* ECM */ + eth_config_driver.label = "CDC Ethernet (ECM)"; + } else { + /* CDC Subset */ + eth_config_driver.label = "CDC Subset/SAFE"; - if((*str == '.') || (*str == ':')) - str++; - num = nibble(*str++) << 4; - num |= (nibble(*str++)); - dev_addr [i] = num; - } - if (is_valid_ether_addr (dev_addr)) - return 0; + device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM), + device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM), + device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; } - random_ether_addr(dev_addr); - return 1; -} - -static int __init -eth_bind (struct usb_gadget *gadget) -{ - struct eth_dev *dev; - struct net_device *net; - u8 cdc = 1, zlp = 1, rndis = 1; - struct usb_ep *in_ep, *out_ep, *status_ep = NULL; - int status = -ENOMEM; - int gcnum; - - /* these flags are only ever cleared; compiler take note */ -#ifndef DEV_CONFIG_CDC - cdc = 0; -#endif -#ifndef CONFIG_USB_ETH_RNDIS - rndis = 0; -#endif - /* Because most host side USB stacks handle CDC Ethernet, that - * standard protocol is _strongly_ preferred for interop purposes. - * (By everyone except Microsoft.) - */ - if (gadget_is_pxa (gadget)) { - /* pxa doesn't support altsettings */ - cdc = 0; - } else if (gadget_is_musbhdrc(gadget)) { - /* reduce tx dma overhead by avoiding special cases */ - zlp = 0; - } else if (gadget_is_sh(gadget)) { - /* sh doesn't support multiple interfaces or configs */ - cdc = 0; - rndis = 0; - } else if (gadget_is_sa1100 (gadget)) { - /* hardware can't write zlps */ - zlp = 0; - /* sa1100 CAN do CDC, without status endpoint ... we use - * non-CDC to be compatible with ARM Linux-2.4 "usb-eth". - */ - cdc = 0; + if (has_rndis()) { + /* RNDIS plus ECM-or-Subset */ + device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM), + device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM), + device_desc.bNumConfigurations = 2; } - gcnum = usb_gadget_controller_number (gadget); + gcnum = usb_gadget_controller_number(gadget); if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum); + device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); else { - /* can't assume CDC works. don't want to default to - * anything less functional on CDC-capable hardware, - * so we fail in this case. + /* We assume that can_support_ecm() tells the truth; + * but if the controller isn't recognized at all then + * that assumption is a bit more likely to be wrong. */ - dev_err (&gadget->dev, - "controller '%s' not recognized\n", - gadget->name); - return -ENODEV; - } - snprintf (manufacturer, sizeof manufacturer, "%s %s/%s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - - /* If there's an RNDIS configuration, that's what Windows wants to - * be using ... so use these product IDs here and in the "linux.inf" - * needed to install MSFT drivers. Current Linux kernels will use - * the second configuration if it's CDC Ethernet, and need some help - * to choose the right configuration otherwise. - */ - if (rndis) { - device_desc.idVendor = - __constant_cpu_to_le16(RNDIS_VENDOR_NUM); - device_desc.idProduct = - __constant_cpu_to_le16(RNDIS_PRODUCT_NUM); - snprintf (product_desc, sizeof product_desc, - "RNDIS/%s", driver_desc); - - /* CDC subset ... recognized by Linux since 2.4.10, but Windows - * drivers aren't widely available. (That may be improved by - * supporting one submode of the "SAFE" variant of MDLM.) - */ - } else if (!cdc) { - device_desc.idVendor = - __constant_cpu_to_le16(SIMPLE_VENDOR_NUM); - device_desc.idProduct = - __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM); - } - - /* support optional vendor/distro customization */ - if (idVendor) { - if (!idProduct) { - dev_err (&gadget->dev, "idVendor needs idProduct!\n"); - return -ENODEV; - } - device_desc.idVendor = cpu_to_le16(idVendor); - device_desc.idProduct = cpu_to_le16(idProduct); - if (bcdDevice) - device_desc.bcdDevice = cpu_to_le16(bcdDevice); - } - if (iManufacturer) - strlcpy (manufacturer, iManufacturer, sizeof manufacturer); - if (iProduct) - strlcpy (product_desc, iProduct, sizeof product_desc); - if (iSerialNumber) { - device_desc.iSerialNumber = STRING_SERIALNUMBER, - strlcpy(serial_number, iSerialNumber, sizeof serial_number); - } - - /* all we really need is bulk IN/OUT */ - usb_ep_autoconfig_reset (gadget); - in_ep = usb_ep_autoconfig (gadget, &fs_source_desc); - if (!in_ep) { -autoconf_fail: - dev_err (&gadget->dev, - "can't autoconfigure on %s\n", - gadget->name); - return -ENODEV; - } - in_ep->driver_data = in_ep; /* claim */ - - out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); - if (!out_ep) - goto autoconf_fail; - out_ep->driver_data = out_ep; /* claim */ - -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - /* CDC Ethernet control interface doesn't require a status endpoint. - * Since some hosts expect one, try to allocate one anyway. - */ - if (cdc || rndis) { - status_ep = usb_ep_autoconfig (gadget, &fs_status_desc); - if (status_ep) { - status_ep->driver_data = status_ep; /* claim */ - } else if (rndis) { - dev_err (&gadget->dev, - "can't run RNDIS on %s\n", - gadget->name); - return -ENODEV; -#ifdef DEV_CONFIG_CDC - /* pxa25x only does CDC subset; often used with RNDIS */ - } else if (cdc) { - control_intf.bNumEndpoints = 0; - /* FIXME remove endpoint from descriptor list */ -#endif - } - } -#endif - - /* one config: cdc, else minimal subset */ - if (!cdc) { - eth_config.bNumInterfaces = 1; - eth_config.iConfiguration = STRING_SUBSET; - - /* use functions to set these up, in case we're built to work - * with multiple controllers and must override CDC Ethernet. - */ - fs_subset_descriptors(); - hs_subset_descriptors(); - } - - device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; - usb_gadget_set_selfpowered (gadget); - - /* For now RNDIS is always a second config */ - if (rndis) - device_desc.bNumConfigurations = 2; - - if (gadget_is_dualspeed(gadget)) { - if (rndis) - dev_qualifier.bNumConfigurations = 2; - else if (!cdc) - dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC; - - /* assumes ep0 uses the same value for both speeds ... */ - dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; - - /* and that all endpoints are dual-speed */ - hs_source_desc.bEndpointAddress = - fs_source_desc.bEndpointAddress; - hs_sink_desc.bEndpointAddress = - fs_sink_desc.bEndpointAddress; -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - if (status_ep) - hs_status_desc.bEndpointAddress = - fs_status_desc.bEndpointAddress; -#endif + WARN(cdev, "controller '%s' not recognized; trying %s\n", + gadget->name, + eth_config_driver.label); + device_desc.bcdDevice = + __constant_cpu_to_le16(0x0300 | 0x0099); } - if (gadget_is_otg(gadget)) { - otg_descriptor.bmAttributes |= USB_OTG_HNP, - eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - eth_config.bMaxPower = 4; -#ifdef CONFIG_USB_ETH_RNDIS - rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - rndis_config.bMaxPower = 4; -#endif - } - - net = alloc_etherdev (sizeof *dev); - if (!net) - return status; - dev = netdev_priv(net); - spin_lock_init (&dev->lock); - spin_lock_init (&dev->req_lock); - INIT_WORK (&dev->work, eth_work); - INIT_LIST_HEAD (&dev->tx_reqs); - INIT_LIST_HEAD (&dev->rx_reqs); - - /* network device setup */ - dev->net = net; - strcpy (net->name, "usb%d"); - dev->cdc = cdc; - dev->zlp = zlp; - dev->in_ep = in_ep; - dev->out_ep = out_ep; - dev->status_ep = status_ep; - - /* Module params for these addresses should come from ID proms. - * The host side address is used with CDC and RNDIS, and commonly - * ends up in a persistent config database. It's not clear if - * host side code for the SAFE thing cares -- its original BLAN - * thing didn't, Sharp never assigned those addresses on Zaurii. + /* Allocate string descriptor numbers ... note that string + * contents can be overridden by the composite_dev glue. */ - if (get_ether_addr(dev_addr, net->dev_addr)) - dev_warn(&gadget->dev, - "using random %s ethernet address\n", "self"); - if (get_ether_addr(host_addr, dev->host_mac)) - dev_warn(&gadget->dev, - "using random %s ethernet address\n", "host"); - snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", - dev->host_mac [0], dev->host_mac [1], - dev->host_mac [2], dev->host_mac [3], - dev->host_mac [4], dev->host_mac [5]); - - if (rndis) { - status = rndis_init(); - if (status < 0) { - dev_err (&gadget->dev, "can't init RNDIS, %d\n", - status); - goto fail; - } - } - net->change_mtu = eth_change_mtu; - net->get_stats = eth_get_stats; - net->hard_start_xmit = eth_start_xmit; - net->open = eth_open; - net->stop = eth_stop; - // watchdog_timeo, tx_timeout ... - // set_multicast_list - SET_ETHTOOL_OPS(net, &ops); + /* device descriptor strings: manufacturer, product */ + snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", + init_utsname()->sysname, init_utsname()->release, + gadget->name); + status = usb_string_id(cdev); + if (status < 0) + goto fail; + strings_dev[STRING_MANUFACTURER_IDX].id = status; + device_desc.iManufacturer = status; - /* preallocate control message data and buffer */ - dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL); - if (!dev->req) + status = usb_string_id(cdev); + if (status < 0) goto fail; - dev->req->complete = eth_setup_complete; + strings_dev[STRING_PRODUCT_IDX].id = status; + device_desc.iProduct = status; - /* ... and maybe likewise for status transfer */ -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - if (dev->status_ep) { - dev->stat_req = eth_req_alloc (dev->status_ep, - STATUS_BYTECOUNT, GFP_KERNEL); - if (!dev->stat_req) { - eth_req_free (gadget->ep0, dev->req); + /* register our configuration(s); RNDIS first, if it's used */ + if (has_rndis()) { + status = usb_add_config(cdev, &rndis_config_driver); + if (status < 0) goto fail; - } - dev->stat_req->context = NULL; } -#endif - - /* finish hookup to lower layer ... */ - dev->gadget = gadget; - set_gadget_data (gadget, dev); - gadget->ep0->driver_data = dev; - /* two kinds of host-initiated state changes: - * - iff DATA transfer is active, carrier is "on" - * - tx queueing enabled if open *and* carrier is "on" - */ - netif_stop_queue (dev->net); - netif_carrier_off (dev->net); - - SET_NETDEV_DEV (dev->net, &gadget->dev); - status = register_netdev (dev->net); + status = usb_add_config(cdev, ð_config_driver); if (status < 0) - goto fail1; - - INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); - INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name, - out_ep->name, in_ep->name, - status_ep ? " STATUS " : "", - status_ep ? status_ep->name : "" - ); - INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - net->dev_addr [0], net->dev_addr [1], - net->dev_addr [2], net->dev_addr [3], - net->dev_addr [4], net->dev_addr [5]); - - if (cdc || rndis) - INFO (dev, "HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->host_mac [0], dev->host_mac [1], - dev->host_mac [2], dev->host_mac [3], - dev->host_mac [4], dev->host_mac [5]); - - if (rndis) { - u32 vendorID = 0; - - /* FIXME RNDIS vendor id == "vendor NIC code" == ? */ - - dev->rndis_config = rndis_register (rndis_control_ack); - if (dev->rndis_config < 0) { -fail0: - unregister_netdev (dev->net); - status = -ENODEV; - goto fail; - } + goto fail; - /* these set up a lot of the OIDs that RNDIS needs */ - rndis_set_host_mac (dev->rndis_config, dev->host_mac); - if (rndis_set_param_dev (dev->rndis_config, dev->net, - &dev->stats, &dev->cdc_filter)) - goto fail0; - if (rndis_set_param_vendor(dev->rndis_config, vendorID, - manufacturer)) - goto fail0; - if (rndis_set_param_medium(dev->rndis_config, - NDIS_MEDIUM_802_3, 0)) - goto fail0; - INFO (dev, "RNDIS ready\n"); - } + INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); - return status; + return 0; -fail1: - dev_dbg(&gadget->dev, "register_netdev failed, %d\n", status); fail: - eth_unbind (gadget); + gether_cleanup(); return status; } -/*-------------------------------------------------------------------------*/ - -static void -eth_suspend (struct usb_gadget *gadget) -{ - struct eth_dev *dev = get_gadget_data (gadget); - - DEBUG (dev, "suspend\n"); - dev->suspended = 1; -} - -static void -eth_resume (struct usb_gadget *gadget) +static int __exit eth_unbind(struct usb_composite_dev *cdev) { - struct eth_dev *dev = get_gadget_data (gadget); - - DEBUG (dev, "resume\n"); - dev->suspended = 0; + gether_cleanup(); + return 0; } -/*-------------------------------------------------------------------------*/ - -static struct usb_gadget_driver eth_driver = { - .speed = DEVSPEED, - - .function = (char *) driver_desc, +static struct usb_composite_driver eth_driver = { + .name = "g_ether", + .dev = &device_desc, + .strings = dev_strings, .bind = eth_bind, - .unbind = eth_unbind, - - .setup = eth_setup, - .disconnect = eth_disconnect, - - .suspend = eth_suspend, - .resume = eth_resume, - - .driver = { - .name = (char *) shortname, - .owner = THIS_MODULE, - }, + .unbind = __exit_p(eth_unbind), }; -MODULE_DESCRIPTION (DRIVER_DESC); -MODULE_AUTHOR ("David Brownell, Benedikt Spanger"); -MODULE_LICENSE ("GPL"); +MODULE_DESCRIPTION(PREFIX DRIVER_DESC); +MODULE_AUTHOR("David Brownell, Benedikt Spanger"); +MODULE_LICENSE("GPL"); - -static int __init init (void) +static int __init init(void) { - return usb_gadget_register_driver (ð_driver); + return usb_composite_register(ð_driver); } -module_init (init); +module_init(init); -static void __exit cleanup (void) +static void __exit cleanup(void) { - usb_gadget_unregister_driver (ð_driver); + usb_composite_unregister(ð_driver); } -module_exit (cleanup); - +module_exit(cleanup); diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c new file mode 100644 index 000000000000..d8faccf27895 --- /dev/null +++ b/drivers/usb/gadget/f_acm.c @@ -0,0 +1,589 @@ +/* + * f_acm.c -- USB CDC serial (ACM) function driver + * + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 by David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * either version 2 of that License or (at your option) any later version. + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/device.h> + +#include "u_serial.h" +#include "gadget_chips.h" + + +/* + * This CDC ACM function support just wraps control functions and + * notifications around the generic serial-over-usb code. + * + * Because CDC ACM is standardized by the USB-IF, many host operating + * systems have drivers for it. Accordingly, ACM is the preferred + * interop solution for serial-port type connections. The control + * models are often not necessary, and in any case don't do much in + * this bare-bones implementation. + * + * Note that even MS-Windows has some support for ACM. However, that + * support is somewhat broken because when you use ACM in a composite + * device, having multiple interfaces confuses the poor OS. It doesn't + * seem to understand CDC Union descriptors. The new "association" + * descriptors (roughly equivalent to CDC Unions) may sometimes help. + */ + +struct acm_ep_descs { + struct usb_endpoint_descriptor *in; + struct usb_endpoint_descriptor *out; + struct usb_endpoint_descriptor *notify; +}; + +struct f_acm { + struct gserial port; + u8 ctrl_id, data_id; + u8 port_num; + + struct usb_descriptor_header **fs_function; + struct acm_ep_descs fs; + struct usb_descriptor_header **hs_function; + struct acm_ep_descs hs; + + struct usb_ep *notify; + struct usb_endpoint_descriptor *notify_desc; + + struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ + u16 port_handshake_bits; +#define RS232_RTS (1 << 1) /* unused with full duplex */ +#define RS232_DTR (1 << 0) /* host is ready for data r/w */ +}; + +static inline struct f_acm *func_to_acm(struct usb_function *f) +{ + return container_of(f, struct f_acm, port.func); +} + +/*-------------------------------------------------------------------------*/ + +/* notification endpoint uses smallish and infrequent fixed-size messages */ + +#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ +#define GS_NOTIFY_MAXPACKET 8 + +/* interface and class descriptors: */ + +static struct usb_interface_descriptor acm_control_interface_desc __initdata = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + /* .bInterfaceNumber = DYNAMIC */ + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_interface_descriptor acm_data_interface_desc __initdata = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + /* .bInterfaceNumber = DYNAMIC */ + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_cdc_header_desc acm_header_desc __initdata = { + .bLength = sizeof(acm_header_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + .bcdCDC = __constant_cpu_to_le16(0x0110), +}; + +static struct usb_cdc_call_mgmt_descriptor +acm_call_mgmt_descriptor __initdata = { + .bLength = sizeof(acm_call_mgmt_descriptor), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, + .bmCapabilities = 0, + /* .bDataInterface = DYNAMIC */ +}; + +static struct usb_cdc_acm_descriptor acm_descriptor __initdata = { + .bLength = sizeof(acm_descriptor), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ACM_TYPE, + .bmCapabilities = (1 << 1), +}; + +static struct usb_cdc_union_desc acm_union_desc __initdata = { + .bLength = sizeof(acm_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_UNION_TYPE, + /* .bMasterInterface0 = DYNAMIC */ + /* .bSlaveInterface0 = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, +}; + +static struct usb_endpoint_descriptor acm_fs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *acm_fs_function[] __initdata = { + (struct usb_descriptor_header *) &acm_control_interface_desc, + (struct usb_descriptor_header *) &acm_header_desc, + (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &acm_union_desc, + (struct usb_descriptor_header *) &acm_fs_notify_desc, + (struct usb_descriptor_header *) &acm_data_interface_desc, + (struct usb_descriptor_header *) &acm_fs_in_desc, + (struct usb_descriptor_header *) &acm_fs_out_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, +}; + +static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *acm_hs_function[] __initdata = { + (struct usb_descriptor_header *) &acm_control_interface_desc, + (struct usb_descriptor_header *) &acm_header_desc, + (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &acm_union_desc, + (struct usb_descriptor_header *) &acm_hs_notify_desc, + (struct usb_descriptor_header *) &acm_data_interface_desc, + (struct usb_descriptor_header *) &acm_hs_in_desc, + (struct usb_descriptor_header *) &acm_hs_out_desc, + NULL, +}; + +/* string descriptors: */ + +#define ACM_CTRL_IDX 0 +#define ACM_DATA_IDX 1 + +/* static strings, in UTF-8 */ +static struct usb_string acm_string_defs[] = { + [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)", + [ACM_DATA_IDX].s = "CDC ACM Data", + { /* ZEROES END LIST */ }, +}; + +static struct usb_gadget_strings acm_string_table = { + .language = 0x0409, /* en-us */ + .strings = acm_string_defs, +}; + +static struct usb_gadget_strings *acm_strings[] = { + &acm_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +/* ACM control ... data handling is delegated to tty library code. + * The main task of this function is to activate and deactivate + * that code based on device state; track parameters like line + * speed, handshake state, and so on; and issue notifications. + */ + +static void acm_complete_set_line_coding(struct usb_ep *ep, + struct usb_request *req) +{ + struct f_acm *acm = ep->driver_data; + struct usb_composite_dev *cdev = acm->port.func.config->cdev; + + if (req->status != 0) { + DBG(cdev, "acm ttyGS%d completion, err %d\n", + acm->port_num, req->status); + return; + } + + /* normal completion */ + if (req->actual != sizeof(acm->port_line_coding)) { + DBG(cdev, "acm ttyGS%d short resp, len %d\n", + acm->port_num, req->actual); + usb_ep_set_halt(ep); + } else { + struct usb_cdc_line_coding *value = req->buf; + + /* REVISIT: we currently just remember this data. + * If we change that, (a) validate it first, then + * (b) update whatever hardware needs updating, + * (c) worry about locking. This is information on + * the order of 9600-8-N-1 ... most of which means + * nothing unless we control a real RS232 line. + */ + acm->port_line_coding = *value; + } +} + +static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) +{ + struct f_acm *acm = func_to_acm(f); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + /* composite driver infrastructure handles everything except + * CDC class messages; interface activation uses set_alt(). + */ + switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { + + /* SET_LINE_CODING ... just read and save what the host sends */ + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_SET_LINE_CODING: + if (w_length != sizeof(struct usb_cdc_line_coding) + || w_index != acm->ctrl_id) + goto invalid; + + value = w_length; + cdev->gadget->ep0->driver_data = acm; + req->complete = acm_complete_set_line_coding; + break; + + /* GET_LINE_CODING ... return what host sent, or initial value */ + case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_GET_LINE_CODING: + if (w_index != acm->ctrl_id) + goto invalid; + + value = min_t(unsigned, w_length, + sizeof(struct usb_cdc_line_coding)); + memcpy(req->buf, &acm->port_line_coding, value); + break; + + /* SET_CONTROL_LINE_STATE ... save what the host sent */ + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_SET_CONTROL_LINE_STATE: + if (w_index != acm->ctrl_id) + goto invalid; + + value = 0; + + /* FIXME we should not allow data to flow until the + * host sets the RS232_DTR bit; and when it clears + * that bit, we should return to that no-flow state. + */ + acm->port_handshake_bits = w_value; + break; + + default: +invalid: + VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n", + acm->port_num, ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; + req->length = value; + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(cdev, "acm response on ttyGS%d, err %d\n", + acm->port_num, value); + } + + /* device either stalls (value < 0) or reports success */ + return value; +} + +static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_acm *acm = func_to_acm(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt == 0, so this is an activation or a reset */ + + if (intf == acm->ctrl_id) { + /* REVISIT this may need more work when we start to + * send notifications ... + */ + if (acm->notify->driver_data) { + VDBG(cdev, "reset acm control interface %d\n", intf); + usb_ep_disable(acm->notify); + } else { + VDBG(cdev, "init acm ctrl interface %d\n", intf); + acm->notify_desc = ep_choose(cdev->gadget, + acm->hs.notify, + acm->fs.notify); + } + usb_ep_enable(acm->notify, acm->notify_desc); + acm->notify->driver_data = acm; + + } else if (intf == acm->data_id) { + if (acm->port.in->driver_data) { + DBG(cdev, "reset acm ttyGS%d\n", acm->port_num); + gserial_disconnect(&acm->port); + } else { + DBG(cdev, "activate acm ttyGS%d\n", acm->port_num); + acm->port.in_desc = ep_choose(cdev->gadget, + acm->hs.in, acm->fs.in); + acm->port.out_desc = ep_choose(cdev->gadget, + acm->hs.out, acm->fs.out); + } + gserial_connect(&acm->port, acm->port_num); + + } else + return -EINVAL; + + return 0; +} + +static void acm_disable(struct usb_function *f) +{ + struct f_acm *acm = func_to_acm(f); + struct usb_composite_dev *cdev = f->config->cdev; + + DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num); + gserial_disconnect(&acm->port); + usb_ep_disable(acm->notify); + acm->notify->driver_data = NULL; +} + +/*-------------------------------------------------------------------------*/ + +/* ACM function driver setup/binding */ +static int __init +acm_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_acm *acm = func_to_acm(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs, and patch descriptors */ + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + acm->ctrl_id = status; + + acm_control_interface_desc.bInterfaceNumber = status; + acm_union_desc .bMasterInterface0 = status; + + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + acm->data_id = status; + + acm_data_interface_desc.bInterfaceNumber = status; + acm_union_desc.bSlaveInterface0 = status; + acm_call_mgmt_descriptor.bDataInterface = status; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc); + if (!ep) + goto fail; + acm->port.in = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc); + if (!ep) + goto fail; + acm->port.out = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc); + if (!ep) + goto fail; + acm->notify = ep; + ep->driver_data = cdev; /* claim */ + + /* copy descriptors, and track endpoint copies */ + f->descriptors = usb_copy_descriptors(acm_fs_function); + + acm->fs.in = usb_find_endpoint(acm_fs_function, + f->descriptors, &acm_fs_in_desc); + acm->fs.out = usb_find_endpoint(acm_fs_function, + f->descriptors, &acm_fs_out_desc); + acm->fs.notify = usb_find_endpoint(acm_fs_function, + f->descriptors, &acm_fs_notify_desc); + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + acm_hs_in_desc.bEndpointAddress = + acm_fs_in_desc.bEndpointAddress; + acm_hs_out_desc.bEndpointAddress = + acm_fs_out_desc.bEndpointAddress; + acm_hs_notify_desc.bEndpointAddress = + acm_fs_notify_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->hs_descriptors = usb_copy_descriptors(acm_hs_function); + + acm->hs.in = usb_find_endpoint(acm_hs_function, + f->hs_descriptors, &acm_hs_in_desc); + acm->hs.out = usb_find_endpoint(acm_hs_function, + f->hs_descriptors, &acm_hs_out_desc); + acm->hs.notify = usb_find_endpoint(acm_hs_function, + f->hs_descriptors, &acm_hs_notify_desc); + } + + /* FIXME provide a callback for triggering notifications */ + + DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", + acm->port_num, + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + acm->port.in->name, acm->port.out->name, + acm->notify->name); + return 0; + +fail: + /* we might as well release our claims on endpoints */ + if (acm->notify) + acm->notify->driver_data = NULL; + if (acm->port.out) + acm->port.out->driver_data = NULL; + if (acm->port.in) + acm->port.in->driver_data = NULL; + + ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status); + + return status; +} + +static void +acm_unbind(struct usb_configuration *c, struct usb_function *f) +{ + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + kfree(func_to_acm(f)); +} + +/* Some controllers can't support CDC ACM ... */ +static inline bool can_support_cdc(struct usb_configuration *c) +{ + /* SH3 doesn't support multiple interfaces */ + if (gadget_is_sh(c->cdev->gadget)) + return false; + + /* sa1100 doesn't have a third interrupt endpoint */ + if (gadget_is_sa1100(c->cdev->gadget)) + return false; + + /* everything else is *probably* fine ... */ + return true; +} + +/** + * acm_bind_config - add a CDC ACM function to a configuration + * @c: the configuration to support the CDC ACM instance + * @port_num: /dev/ttyGS* port this interface will use + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gserial_setup() with enough ports to + * handle all the ones it binds. Caller is also responsible + * for calling @gserial_cleanup() before module unload. + */ +int __init acm_bind_config(struct usb_configuration *c, u8 port_num) +{ + struct f_acm *acm; + int status; + + if (!can_support_cdc(c)) + return -EINVAL; + + /* REVISIT might want instance-specific strings to help + * distinguish instances ... + */ + + /* maybe allocate device-global string IDs, and patch descriptors */ + if (acm_string_defs[ACM_CTRL_IDX].id == 0) { + status = usb_string_id(c->cdev); + if (status < 0) + return status; + acm_string_defs[ACM_CTRL_IDX].id = status; + + acm_control_interface_desc.iInterface = status; + + status = usb_string_id(c->cdev); + if (status < 0) + return status; + acm_string_defs[ACM_DATA_IDX].id = status; + + acm_data_interface_desc.iInterface = status; + } + + /* allocate and initialize one new instance */ + acm = kzalloc(sizeof *acm, GFP_KERNEL); + if (!acm) + return -ENOMEM; + + acm->port_num = port_num; + + acm->port.func.name = "acm"; + acm->port.func.strings = acm_strings; + /* descriptors are per-instance copies */ + acm->port.func.bind = acm_bind; + acm->port.func.unbind = acm_unbind; + acm->port.func.set_alt = acm_set_alt; + acm->port.func.setup = acm_setup; + acm->port.func.disable = acm_disable; + + status = usb_add_function(c, &acm->port.func); + if (status) + kfree(acm); + return status; +} diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c new file mode 100644 index 000000000000..0822e9d7693a --- /dev/null +++ b/drivers/usb/gadget/f_ecm.c @@ -0,0 +1,833 @@ +/* + * f_ecm.c -- USB CDC Ethernet (ECM) link function driver + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/etherdevice.h> + +#include "u_ether.h" + + +/* + * This function is a "CDC Ethernet Networking Control Model" (CDC ECM) + * Ethernet link. The data transfer model is simple (packets sent and + * received over bulk endpoints using normal short packet termination), + * and the control model exposes various data and optional notifications. + * + * ECM is well standardized and (except for Microsoft) supported by most + * operating systems with USB host support. It's the preferred interop + * solution for Ethernet over USB, at least for firmware based solutions. + * (Hardware solutions tend to be more minimalist.) A newer and simpler + * "Ethernet Emulation Model" (CDC EEM) hasn't yet caught on. + * + * Note that ECM requires the use of "alternate settings" for its data + * interface. This means that the set_alt() method has real work to do, + * and also means that a get_alt() method is required. + */ + +struct ecm_ep_descs { + struct usb_endpoint_descriptor *in; + struct usb_endpoint_descriptor *out; + struct usb_endpoint_descriptor *notify; +}; + +enum ecm_notify_state { + ECM_NOTIFY_NONE, /* don't notify */ + ECM_NOTIFY_CONNECT, /* issue CONNECT next */ + ECM_NOTIFY_SPEED, /* issue SPEED_CHANGE next */ +}; + +struct f_ecm { + struct gether port; + u8 ctrl_id, data_id; + + char ethaddr[14]; + + struct usb_descriptor_header **fs_function; + struct ecm_ep_descs fs; + struct usb_descriptor_header **hs_function; + struct ecm_ep_descs hs; + + struct usb_ep *notify; + struct usb_endpoint_descriptor *notify_desc; + struct usb_request *notify_req; + u8 notify_state; + bool is_open; + + /* FIXME is_open needs some irq-ish locking + * ... possibly the same as port.ioport + */ +}; + +static inline struct f_ecm *func_to_ecm(struct usb_function *f) +{ + return container_of(f, struct f_ecm, port.func); +} + +/* peak (theoretical) bulk transfer rate in bits-per-second */ +static inline unsigned bitrate(struct usb_gadget *g) +{ + if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return 13 * 512 * 8 * 1000 * 8; + else + return 19 * 64 * 1 * 1000 * 8; +} + +/*-------------------------------------------------------------------------*/ + +/* + * Include the status endpoint if we can, even though it's optional. + * + * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one + * packet, to simplify cancellation; and a big transfer interval, to + * waste less bandwidth. + * + * Some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even + * if they ignore the connect/disconnect notifications that real aether + * can provide. More advanced cdc configurations might want to support + * encapsulated commands (vendor-specific, using control-OUT). + */ + +#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ +#define STATUS_BYTECOUNT 16 /* 8 byte header + data */ + + +/* interface descriptor: */ + +static struct usb_interface_descriptor ecm_control_intf __initdata = { + .bLength = sizeof ecm_control_intf, + .bDescriptorType = USB_DT_INTERFACE, + + /* .bInterfaceNumber = DYNAMIC */ + /* status endpoint is optional; this could be patched later */ + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_cdc_header_desc header_desc __initdata = { + .bLength = sizeof header_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + + .bcdCDC = __constant_cpu_to_le16(0x0110), +}; + +static struct usb_cdc_union_desc ecm_union_desc __initdata = { + .bLength = sizeof(ecm_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_UNION_TYPE, + /* .bMasterInterface0 = DYNAMIC */ + /* .bSlaveInterface0 = DYNAMIC */ +}; + +static struct usb_cdc_ether_desc ether_desc __initdata = { + .bLength = sizeof ether_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, + + /* this descriptor actually adds value, surprise! */ + /* .iMACAddress = DYNAMIC */ + .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = __constant_cpu_to_le16(0), + .bNumberPowerFilters = 0, +}; + +/* the default data interface has no endpoints ... */ + +static struct usb_interface_descriptor ecm_data_nop_intf __initdata = { + .bLength = sizeof ecm_data_nop_intf, + .bDescriptorType = USB_DT_INTERFACE, + + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +/* ... but the "real" data interface has two bulk endpoints */ + +static struct usb_interface_descriptor ecm_data_intf __initdata = { + .bLength = sizeof ecm_data_intf, + .bDescriptorType = USB_DT_INTERFACE, + + .bInterfaceNumber = 1, + .bAlternateSetting = 1, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor fs_notify_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, +}; + +static struct usb_endpoint_descriptor fs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor fs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *eth_fs_function[] __initdata = { + /* CDC ECM control descriptors */ + (struct usb_descriptor_header *) &ecm_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &ecm_union_desc, + (struct usb_descriptor_header *) ðer_desc, + /* NOTE: status endpoint might need to be removed */ + (struct usb_descriptor_header *) &fs_notify_desc, + /* data interface, altsettings 0 and 1 */ + (struct usb_descriptor_header *) &ecm_data_nop_intf, + (struct usb_descriptor_header *) &ecm_data_intf, + (struct usb_descriptor_header *) &fs_in_desc, + (struct usb_descriptor_header *) &fs_out_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor hs_notify_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, +}; +static struct usb_endpoint_descriptor hs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor hs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *eth_hs_function[] __initdata = { + /* CDC ECM control descriptors */ + (struct usb_descriptor_header *) &ecm_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &ecm_union_desc, + (struct usb_descriptor_header *) ðer_desc, + /* NOTE: status endpoint might need to be removed */ + (struct usb_descriptor_header *) &hs_notify_desc, + /* data interface, altsettings 0 and 1 */ + (struct usb_descriptor_header *) &ecm_data_nop_intf, + (struct usb_descriptor_header *) &ecm_data_intf, + (struct usb_descriptor_header *) &hs_in_desc, + (struct usb_descriptor_header *) &hs_out_desc, + NULL, +}; + +/* string descriptors: */ + +static struct usb_string ecm_string_defs[] = { + [0].s = "CDC Ethernet Control Model (ECM)", + [1].s = NULL /* DYNAMIC */, + [2].s = "CDC Ethernet Data", + { } /* end of list */ +}; + +static struct usb_gadget_strings ecm_string_table = { + .language = 0x0409, /* en-us */ + .strings = ecm_string_defs, +}; + +static struct usb_gadget_strings *ecm_strings[] = { + &ecm_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static void ecm_do_notify(struct f_ecm *ecm) +{ + struct usb_request *req = ecm->notify_req; + struct usb_cdc_notification *event; + struct usb_composite_dev *cdev = ecm->port.func.config->cdev; + __le32 *data; + int status; + + /* notification already in flight? */ + if (!req) + return; + + event = req->buf; + switch (ecm->notify_state) { + case ECM_NOTIFY_NONE: + return; + + case ECM_NOTIFY_CONNECT: + event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION; + if (ecm->is_open) + event->wValue = cpu_to_le16(1); + else + event->wValue = cpu_to_le16(0); + event->wLength = 0; + req->length = sizeof *event; + + DBG(cdev, "notify connect %s\n", + ecm->is_open ? "true" : "false"); + ecm->notify_state = ECM_NOTIFY_SPEED; + break; + + case ECM_NOTIFY_SPEED: + event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE; + event->wValue = cpu_to_le16(0); + event->wLength = cpu_to_le16(8); + req->length = STATUS_BYTECOUNT; + + /* SPEED_CHANGE data is up/down speeds in bits/sec */ + data = req->buf + sizeof *event; + data[0] = cpu_to_le32(bitrate(cdev->gadget)); + data[1] = data[0]; + + DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget)); + ecm->notify_state = ECM_NOTIFY_NONE; + break; + } + event->bmRequestType = 0xA1; + event->wIndex = cpu_to_le16(ecm->ctrl_id); + + ecm->notify_req = NULL; + status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC); + if (status < 0) { + ecm->notify_req = req; + DBG(cdev, "notify --> %d\n", status); + } +} + +static void ecm_notify(struct f_ecm *ecm) +{ + /* NOTE on most versions of Linux, host side cdc-ethernet + * won't listen for notifications until its netdevice opens. + * The first notification then sits in the FIFO for a long + * time, and the second one is queued. + */ + ecm->notify_state = ECM_NOTIFY_CONNECT; + ecm_do_notify(ecm); +} + +static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_ecm *ecm = req->context; + struct usb_composite_dev *cdev = ecm->port.func.config->cdev; + struct usb_cdc_notification *event = req->buf; + + switch (req->status) { + case 0: + /* no fault */ + break; + case -ECONNRESET: + case -ESHUTDOWN: + ecm->notify_state = ECM_NOTIFY_NONE; + break; + default: + DBG(cdev, "event %02x --> %d\n", + event->bNotificationType, req->status); + break; + } + ecm->notify_req = req; + ecm_do_notify(ecm); +} + +static int ecm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) +{ + struct f_ecm *ecm = func_to_ecm(f); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + /* composite driver infrastructure handles everything except + * CDC class messages; interface activation uses set_alt(). + */ + switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_SET_ETHERNET_PACKET_FILTER: + /* see 6.2.30: no data, wIndex = interface, + * wValue = packet filter bitmap + */ + if (w_length != 0 || w_index != ecm->ctrl_id) + goto invalid; + DBG(cdev, "packet filter %02x\n", w_value); + /* REVISIT locking of cdc_filter. This assumes the UDC + * driver won't have a concurrent packet TX irq running on + * another CPU; or that if it does, this write is atomic... + */ + ecm->port.cdc_filter = w_value; + value = 0; + break; + + /* and optionally: + * case USB_CDC_SEND_ENCAPSULATED_COMMAND: + * case USB_CDC_GET_ENCAPSULATED_RESPONSE: + * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS: + * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER: + * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER: + * case USB_CDC_GET_ETHERNET_STATISTIC: + */ + + default: +invalid: + DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + DBG(cdev, "ecm req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; + req->length = value; + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(cdev, "ecm req %02x.%02x response err %d\n", + ctrl->bRequestType, ctrl->bRequest, + value); + } + + /* device either stalls (value < 0) or reports success */ + return value; +} + + +static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_ecm *ecm = func_to_ecm(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* Control interface has only altsetting 0 */ + if (intf == ecm->ctrl_id) { + if (alt != 0) + goto fail; + + if (ecm->notify->driver_data) { + VDBG(cdev, "reset ecm control %d\n", intf); + usb_ep_disable(ecm->notify); + } else { + VDBG(cdev, "init ecm ctrl %d\n", intf); + ecm->notify_desc = ep_choose(cdev->gadget, + ecm->hs.notify, + ecm->fs.notify); + } + usb_ep_enable(ecm->notify, ecm->notify_desc); + ecm->notify->driver_data = ecm; + + /* Data interface has two altsettings, 0 and 1 */ + } else if (intf == ecm->data_id) { + if (alt > 1) + goto fail; + + if (ecm->port.in_ep->driver_data) { + DBG(cdev, "reset ecm\n"); + gether_disconnect(&ecm->port); + } + + if (!ecm->port.in) { + DBG(cdev, "init ecm\n"); + ecm->port.in = ep_choose(cdev->gadget, + ecm->hs.in, ecm->fs.in); + ecm->port.out = ep_choose(cdev->gadget, + ecm->hs.out, ecm->fs.out); + } + + /* CDC Ethernet only sends data in non-default altsettings. + * Changing altsettings resets filters, statistics, etc. + */ + if (alt == 1) { + struct net_device *net; + + /* Enable zlps by default for ECM conformance; + * override for musb_hdrc (avoids txdma ovhead) + * and sa1100 (can't). + */ + ecm->port.is_zlp_ok = !( + gadget_is_sa1100(cdev->gadget) + || gadget_is_musbhdrc(cdev->gadget) + ); + ecm->port.cdc_filter = DEFAULT_FILTER; + DBG(cdev, "activate ecm\n"); + net = gether_connect(&ecm->port); + if (IS_ERR(net)) + return PTR_ERR(net); + } + + /* NOTE this can be a minor disagreement with the ECM spec, + * which says speed notifications will "always" follow + * connection notifications. But we allow one connect to + * follow another (if the first is in flight), and instead + * just guarantee that a speed notification is always sent. + */ + ecm_notify(ecm); + } else + goto fail; + + return 0; +fail: + return -EINVAL; +} + +/* Because the data interface supports multiple altsettings, + * this ECM function *MUST* implement a get_alt() method. + */ +static int ecm_get_alt(struct usb_function *f, unsigned intf) +{ + struct f_ecm *ecm = func_to_ecm(f); + + if (intf == ecm->ctrl_id) + return 0; + return ecm->port.in_ep->driver_data ? 1 : 0; +} + +static void ecm_disable(struct usb_function *f) +{ + struct f_ecm *ecm = func_to_ecm(f); + struct usb_composite_dev *cdev = f->config->cdev; + + DBG(cdev, "ecm deactivated\n"); + + if (ecm->port.in_ep->driver_data) + gether_disconnect(&ecm->port); + + if (ecm->notify->driver_data) { + usb_ep_disable(ecm->notify); + ecm->notify->driver_data = NULL; + ecm->notify_desc = NULL; + } +} + +/*-------------------------------------------------------------------------*/ + +/* + * Callbacks let us notify the host about connect/disconnect when the + * net device is opened or closed. + * + * For testing, note that link states on this side include both opened + * and closed variants of: + * + * - disconnected/unconfigured + * - configured but inactive (data alt 0) + * - configured and active (data alt 1) + * + * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and + * SET_INTERFACE (altsetting). Remember also that "configured" doesn't + * imply the host is actually polling the notification endpoint, and + * likewise that "active" doesn't imply it's actually using the data + * endpoints for traffic. + */ + +static void ecm_open(struct gether *geth) +{ + struct f_ecm *ecm = func_to_ecm(&geth->func); + + DBG(ecm->port.func.config->cdev, "%s\n", __func__); + + ecm->is_open = true; + ecm_notify(ecm); +} + +static void ecm_close(struct gether *geth) +{ + struct f_ecm *ecm = func_to_ecm(&geth->func); + + DBG(ecm->port.func.config->cdev, "%s\n", __func__); + + ecm->is_open = false; + ecm_notify(ecm); +} + +/*-------------------------------------------------------------------------*/ + +/* ethernet function driver setup/binding */ + +static int __init +ecm_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_ecm *ecm = func_to_ecm(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs */ + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + ecm->ctrl_id = status; + + ecm_control_intf.bInterfaceNumber = status; + ecm_union_desc.bMasterInterface0 = status; + + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + ecm->data_id = status; + + ecm_data_nop_intf.bInterfaceNumber = status; + ecm_data_intf.bInterfaceNumber = status; + ecm_union_desc.bSlaveInterface0 = status; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); + if (!ep) + goto fail; + ecm->port.in_ep = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc); + if (!ep) + goto fail; + ecm->port.out_ep = ep; + ep->driver_data = cdev; /* claim */ + + /* NOTE: a status/notification endpoint is *OPTIONAL* but we + * don't treat it that way. It's simpler, and some newer CDC + * profiles (wireless handsets) no longer treat it as optional. + */ + ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc); + if (!ep) + goto fail; + ecm->notify = ep; + ep->driver_data = cdev; /* claim */ + + status = -ENOMEM; + + /* allocate notification request and buffer */ + ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); + if (!ecm->notify_req) + goto fail; + ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL); + if (!ecm->notify_req->buf) + goto fail; + ecm->notify_req->context = ecm; + ecm->notify_req->complete = ecm_notify_complete; + + /* copy descriptors, and track endpoint copies */ + f->descriptors = usb_copy_descriptors(eth_fs_function); + if (!f->descriptors) + goto fail; + + ecm->fs.in = usb_find_endpoint(eth_fs_function, + f->descriptors, &fs_in_desc); + ecm->fs.out = usb_find_endpoint(eth_fs_function, + f->descriptors, &fs_out_desc); + ecm->fs.notify = usb_find_endpoint(eth_fs_function, + f->descriptors, &fs_notify_desc); + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + hs_in_desc.bEndpointAddress = + fs_in_desc.bEndpointAddress; + hs_out_desc.bEndpointAddress = + fs_out_desc.bEndpointAddress; + hs_notify_desc.bEndpointAddress = + fs_notify_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->hs_descriptors = usb_copy_descriptors(eth_hs_function); + if (!f->hs_descriptors) + goto fail; + + ecm->hs.in = usb_find_endpoint(eth_hs_function, + f->hs_descriptors, &hs_in_desc); + ecm->hs.out = usb_find_endpoint(eth_hs_function, + f->hs_descriptors, &hs_out_desc); + ecm->hs.notify = usb_find_endpoint(eth_hs_function, + f->hs_descriptors, &hs_notify_desc); + } + + /* NOTE: all that is done without knowing or caring about + * the network link ... which is unavailable to this code + * until we're activated via set_alt(). + */ + + ecm->port.open = ecm_open; + ecm->port.close = ecm_close; + + DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n", + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + ecm->port.in_ep->name, ecm->port.out_ep->name, + ecm->notify->name); + return 0; + +fail: + if (f->descriptors) + usb_free_descriptors(f->descriptors); + + if (ecm->notify_req) { + kfree(ecm->notify_req->buf); + usb_ep_free_request(ecm->notify, ecm->notify_req); + } + + /* we might as well release our claims on endpoints */ + if (ecm->notify) + ecm->notify->driver_data = NULL; + if (ecm->port.out) + ecm->port.out_ep->driver_data = NULL; + if (ecm->port.in) + ecm->port.in_ep->driver_data = NULL; + + ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); + + return status; +} + +static void +ecm_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct f_ecm *ecm = func_to_ecm(f); + + DBG(c->cdev, "ecm unbind\n"); + + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + + kfree(ecm->notify_req->buf); + usb_ep_free_request(ecm->notify, ecm->notify_req); + + ecm_string_defs[1].s = NULL; + kfree(ecm); +} + +/** + * ecm_bind_config - add CDC Ethernet network link to a configuration + * @c: the configuration to support the network link + * @ethaddr: a buffer in which the ethernet address of the host side + * side of the link was recorded + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gether_setup(). Caller is also responsible + * for calling @gether_cleanup() before module unload. + */ +int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +{ + struct f_ecm *ecm; + int status; + + if (!can_support_ecm(c->cdev->gadget) || !ethaddr) + return -EINVAL; + + /* maybe allocate device-global string IDs */ + if (ecm_string_defs[0].id == 0) { + + /* control interface label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + ecm_string_defs[0].id = status; + ecm_control_intf.iInterface = status; + + /* data interface label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + ecm_string_defs[2].id = status; + ecm_data_intf.iInterface = status; + + /* MAC address */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + ecm_string_defs[1].id = status; + ether_desc.iMACAddress = status; + } + + /* allocate and initialize one new instance */ + ecm = kzalloc(sizeof *ecm, GFP_KERNEL); + if (!ecm) + return -ENOMEM; + + /* export host's Ethernet address in CDC format */ + snprintf(ecm->ethaddr, sizeof ecm->ethaddr, + "%02X%02X%02X%02X%02X%02X", + ethaddr[0], ethaddr[1], ethaddr[2], + ethaddr[3], ethaddr[4], ethaddr[5]); + ecm_string_defs[1].s = ecm->ethaddr; + + ecm->port.cdc_filter = DEFAULT_FILTER; + + ecm->port.func.name = "cdc_ethernet"; + ecm->port.func.strings = ecm_strings; + /* descriptors are per-instance copies */ + ecm->port.func.bind = ecm_bind; + ecm->port.func.unbind = ecm_unbind; + ecm->port.func.set_alt = ecm_set_alt; + ecm->port.func.get_alt = ecm_get_alt; + ecm->port.func.setup = ecm_setup; + ecm->port.func.disable = ecm_disable; + + status = usb_add_function(c, &ecm->port.func); + if (status) { + ecm_string_defs[1].s = NULL; + kfree(ecm); + } + return status; +} diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c new file mode 100644 index 000000000000..eda4cde72c82 --- /dev/null +++ b/drivers/usb/gadget/f_loopback.c @@ -0,0 +1,381 @@ +/* + * f_loopback.c - USB peripheral loopback configuration driver + * + * Copyright (C) 2003-2008 David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/utsname.h> +#include <linux/device.h> + +#include "g_zero.h" +#include "gadget_chips.h" + + +/* + * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals, + * + * This takes messages of various sizes written OUT to a device, and loops + * them back so they can be read IN from it. It has been used by certain + * test applications. It supports limited testing of data queueing logic. + * + * + * This is currently packaged as a configuration driver, which can't be + * combined with other functions to make composite devices. However, it + * can be combined with other independent configurations. + */ +struct f_loopback { + struct usb_function function; + + struct usb_ep *in_ep; + struct usb_ep *out_ep; +}; + +static inline struct f_loopback *func_to_loop(struct usb_function *f) +{ + return container_of(f, struct f_loopback, function); +} + +static unsigned qlen = 32; +module_param(qlen, uint, 0); +MODULE_PARM_DESC(qlenn, "depth of loopback queue"); + +/*-------------------------------------------------------------------------*/ + +static struct usb_interface_descriptor loopback_intf = { + .bLength = sizeof loopback_intf, + .bDescriptorType = USB_DT_INTERFACE, + + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + /* .iInterface = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor fs_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor fs_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *fs_loopback_descs[] = { + (struct usb_descriptor_header *) &loopback_intf, + (struct usb_descriptor_header *) &fs_sink_desc, + (struct usb_descriptor_header *) &fs_source_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor hs_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor hs_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *hs_loopback_descs[] = { + (struct usb_descriptor_header *) &loopback_intf, + (struct usb_descriptor_header *) &hs_source_desc, + (struct usb_descriptor_header *) &hs_sink_desc, + NULL, +}; + +/* function-specific strings: */ + +static struct usb_string strings_loopback[] = { + [0].s = "loop input to output", + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_loop = { + .language = 0x0409, /* en-us */ + .strings = strings_loopback, +}; + +static struct usb_gadget_strings *loopback_strings[] = { + &stringtab_loop, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static int __init +loopback_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_loopback *loop = func_to_loop(f); + int id; + + /* allocate interface ID(s) */ + id = usb_interface_id(c, f); + if (id < 0) + return id; + loopback_intf.bInterfaceNumber = id; + + /* allocate endpoints */ + + loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); + if (!loop->in_ep) { +autoconf_fail: + ERROR(cdev, "%s: can't autoconfigure on %s\n", + f->name, cdev->gadget->name); + return -ENODEV; + } + loop->in_ep->driver_data = cdev; /* claim */ + + loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc); + if (!loop->out_ep) + goto autoconf_fail; + loop->out_ep->driver_data = cdev; /* claim */ + + /* support high speed hardware */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + hs_source_desc.bEndpointAddress = + fs_source_desc.bEndpointAddress; + hs_sink_desc.bEndpointAddress = + fs_sink_desc.bEndpointAddress; + f->hs_descriptors = hs_loopback_descs; + } + + DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + f->name, loop->in_ep->name, loop->out_ep->name); + return 0; +} + +static void +loopback_unbind(struct usb_configuration *c, struct usb_function *f) +{ + kfree(func_to_loop(f)); +} + +static void loopback_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_loopback *loop = ep->driver_data; + struct usb_composite_dev *cdev = loop->function.config->cdev; + int status = req->status; + + switch (status) { + + case 0: /* normal completion? */ + if (ep == loop->out_ep) { + /* loop this OUT packet back IN to the host */ + req->zero = (req->actual < req->length); + req->length = req->actual; + status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC); + if (status == 0) + return; + + /* "should never get here" */ + ERROR(cdev, "can't loop %s to %s: %d\n", + ep->name, loop->in_ep->name, + status); + } + + /* queue the buffer for some later OUT packet */ + req->length = buflen; + status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC); + if (status == 0) + return; + + /* "should never get here" */ + /* FALLTHROUGH */ + + default: + ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name, + status, req->actual, req->length); + /* FALLTHROUGH */ + + /* NOTE: since this driver doesn't maintain an explicit record + * of requests it submitted (just maintains qlen count), we + * rely on the hardware driver to clean up on disconnect or + * endpoint disable. + */ + case -ECONNABORTED: /* hardware forced ep reset */ + case -ECONNRESET: /* request dequeued */ + case -ESHUTDOWN: /* disconnect from host */ + free_ep_req(ep, req); + return; + } +} + +static void disable_loopback(struct f_loopback *loop) +{ + struct usb_composite_dev *cdev; + + cdev = loop->function.config->cdev; + disable_endpoints(cdev, loop->in_ep, loop->out_ep); + VDBG(cdev, "%s disabled\n", loop->function.name); +} + +static int +enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) +{ + int result = 0; + const struct usb_endpoint_descriptor *src, *sink; + struct usb_ep *ep; + struct usb_request *req; + unsigned i; + + src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc); + sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc); + + /* one endpoint writes data back IN to the host */ + ep = loop->in_ep; + result = usb_ep_enable(ep, src); + if (result < 0) + return result; + ep->driver_data = loop; + + /* one endpoint just reads OUT packets */ + ep = loop->out_ep; + result = usb_ep_enable(ep, sink); + if (result < 0) { +fail0: + ep = loop->in_ep; + usb_ep_disable(ep); + ep->driver_data = NULL; + return result; + } + ep->driver_data = loop; + + /* allocate a bunch of read buffers and queue them all at once. + * we buffer at most 'qlen' transfers; fewer if any need more + * than 'buflen' bytes each. + */ + for (i = 0; i < qlen && result == 0; i++) { + req = alloc_ep_req(ep); + if (req) { + req->complete = loopback_complete; + result = usb_ep_queue(ep, req, GFP_ATOMIC); + if (result) + ERROR(cdev, "%s queue req --> %d\n", + ep->name, result); + } else { + usb_ep_disable(ep); + ep->driver_data = NULL; + result = -ENOMEM; + goto fail0; + } + } + + DBG(cdev, "%s enabled\n", loop->function.name); + return result; +} + +static int loopback_set_alt(struct usb_function *f, + unsigned intf, unsigned alt) +{ + struct f_loopback *loop = func_to_loop(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt is zero */ + if (loop->in_ep->driver_data) + disable_loopback(loop); + return enable_loopback(cdev, loop); +} + +static void loopback_disable(struct usb_function *f) +{ + struct f_loopback *loop = func_to_loop(f); + + disable_loopback(loop); +} + +/*-------------------------------------------------------------------------*/ + +static int __init loopback_bind_config(struct usb_configuration *c) +{ + struct f_loopback *loop; + int status; + + loop = kzalloc(sizeof *loop, GFP_KERNEL); + if (!loop) + return -ENOMEM; + + loop->function.name = "loopback"; + loop->function.descriptors = fs_loopback_descs; + loop->function.bind = loopback_bind; + loop->function.unbind = loopback_unbind; + loop->function.set_alt = loopback_set_alt; + loop->function.disable = loopback_disable; + + status = usb_add_function(c, &loop->function); + if (status) + kfree(loop); + return status; +} + +static struct usb_configuration loopback_driver = { + .label = "loopback", + .strings = loopback_strings, + .bind = loopback_bind_config, + .bConfigurationValue = 2, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* 2 mA, minimal */ + /* .iConfiguration = DYNAMIC */ +}; + +/** + * loopback_add - add a loopback testing configuration to a device + * @cdev: the device to support the loopback configuration + */ +int __init loopback_add(struct usb_composite_dev *cdev) +{ + int id; + + /* allocate string ID(s) */ + id = usb_string_id(cdev); + if (id < 0) + return id; + strings_loopback[0].id = id; + + loopback_intf.iInterface = id; + loopback_driver.iConfiguration = id; + + /* support OTG systems */ + if (gadget_is_otg(cdev->gadget)) { + loopback_driver.descriptors = otg_desc; + loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + return usb_add_config(cdev, &loopback_driver); +} diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c new file mode 100644 index 000000000000..61652f0f13fd --- /dev/null +++ b/drivers/usb/gadget/f_rndis.c @@ -0,0 +1,827 @@ +/* + * f_rndis.c -- RNDIS link function driver + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/etherdevice.h> + +#include <asm/atomic.h> + +#include "u_ether.h" +#include "rndis.h" + + +/* + * This function is an RNDIS Ethernet port -- a Microsoft protocol that's + * been promoted instead of the standard CDC Ethernet. The published RNDIS + * spec is ambiguous, incomplete, and needlessly complex. Variants such as + * ActiveSync have even worse status in terms of specification. + * + * In short: it's a protocol controlled by (and for) Microsoft, not for an + * Open ecosystem or markets. Linux supports it *only* because Microsoft + * doesn't support the CDC Ethernet standard. + * + * The RNDIS data transfer model is complex, with multiple Ethernet packets + * per USB message, and out of band data. The control model is built around + * what's essentially an "RNDIS RPC" protocol. It's all wrapped in a CDC ACM + * (modem, not Ethernet) veneer, with those ACM descriptors being entirely + * useless (they're ignored). RNDIS expects to be the only function in its + * configuration, so it's no real help if you need composite devices; and + * it expects to be the first configuration too. + * + * There is a single technical advantage of RNDIS over CDC Ethernet, if you + * discount the fluff that its RPC can be made to deliver: it doesn't need + * a NOP altsetting for the data interface. That lets it work on some of the + * "so smart it's stupid" hardware which takes over configuration changes + * from the software, and adds restrictions like "no altsettings". + * + * Unfortunately MSFT's RNDIS drivers are buggy. They hang or oops, and + * have all sorts of contrary-to-specification oddities that can prevent + * them from working sanely. Since bugfixes (or accurate specs, letting + * Linux work around those bugs) are unlikely to ever come from MSFT, you + * may want to avoid using RNDIS on purely operational grounds. + * + * Omissions from the RNDIS 1.0 specification include: + * + * - Power management ... references data that's scattered around lots + * of other documentation, which is incorrect/incomplete there too. + * + * - There are various undocumented protocol requirements, like the need + * to send garbage in some control-OUT messages. + * + * - MS-Windows drivers sometimes emit undocumented requests. + */ + +struct rndis_ep_descs { + struct usb_endpoint_descriptor *in; + struct usb_endpoint_descriptor *out; + struct usb_endpoint_descriptor *notify; +}; + +struct f_rndis { + struct gether port; + u8 ctrl_id, data_id; + u8 ethaddr[ETH_ALEN]; + int config; + + struct usb_descriptor_header **fs_function; + struct rndis_ep_descs fs; + struct usb_descriptor_header **hs_function; + struct rndis_ep_descs hs; + + struct usb_ep *notify; + struct usb_endpoint_descriptor *notify_desc; + struct usb_request *notify_req; + atomic_t notify_count; +}; + +static inline struct f_rndis *func_to_rndis(struct usb_function *f) +{ + return container_of(f, struct f_rndis, port.func); +} + +/* peak (theoretical) bulk transfer rate in bits-per-second */ +static unsigned int bitrate(struct usb_gadget *g) +{ + if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return 13 * 512 * 8 * 1000 * 8; + else + return 19 * 64 * 1 * 1000 * 8; +} + +/*-------------------------------------------------------------------------*/ + +/* + */ + +#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ +#define STATUS_BYTECOUNT 8 /* 8 bytes data */ + + +/* interface descriptor: */ + +static struct usb_interface_descriptor rndis_control_intf __initdata = { + .bLength = sizeof rndis_control_intf, + .bDescriptorType = USB_DT_INTERFACE, + + /* .bInterfaceNumber = DYNAMIC */ + /* status endpoint is optional; this could be patched later */ + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_cdc_header_desc header_desc __initdata = { + .bLength = sizeof header_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + + .bcdCDC = __constant_cpu_to_le16(0x0110), +}; + +static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = { + .bLength = sizeof call_mgmt_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, + + .bmCapabilities = 0x00, + .bDataInterface = 0x01, +}; + +static struct usb_cdc_acm_descriptor acm_descriptor __initdata = { + .bLength = sizeof acm_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ACM_TYPE, + + .bmCapabilities = 0x00, +}; + +static struct usb_cdc_union_desc rndis_union_desc __initdata = { + .bLength = sizeof(rndis_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_UNION_TYPE, + /* .bMasterInterface0 = DYNAMIC */ + /* .bSlaveInterface0 = DYNAMIC */ +}; + +/* the data interface has two bulk endpoints */ + +static struct usb_interface_descriptor rndis_data_intf __initdata = { + .bLength = sizeof rndis_data_intf, + .bDescriptorType = USB_DT_INTERFACE, + + /* .bInterfaceNumber = DYNAMIC */ + .bAlternateSetting = 1, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor fs_notify_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, +}; + +static struct usb_endpoint_descriptor fs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor fs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *eth_fs_function[] __initdata = { + /* control interface matches ACM, not Ethernet */ + (struct usb_descriptor_header *) &rndis_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &rndis_union_desc, + (struct usb_descriptor_header *) &fs_notify_desc, + /* data interface has no altsetting */ + (struct usb_descriptor_header *) &rndis_data_intf, + (struct usb_descriptor_header *) &fs_in_desc, + (struct usb_descriptor_header *) &fs_out_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor hs_notify_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, +}; +static struct usb_endpoint_descriptor hs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor hs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *eth_hs_function[] __initdata = { + /* control interface matches ACM, not Ethernet */ + (struct usb_descriptor_header *) &rndis_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &rndis_union_desc, + (struct usb_descriptor_header *) &hs_notify_desc, + /* data interface has no altsetting */ + (struct usb_descriptor_header *) &rndis_data_intf, + (struct usb_descriptor_header *) &hs_in_desc, + (struct usb_descriptor_header *) &hs_out_desc, + NULL, +}; + +/* string descriptors: */ + +static struct usb_string rndis_string_defs[] = { + [0].s = "RNDIS Communications Control", + [1].s = "RNDIS Ethernet Data", + { } /* end of list */ +}; + +static struct usb_gadget_strings rndis_string_table = { + .language = 0x0409, /* en-us */ + .strings = rndis_string_defs, +}; + +static struct usb_gadget_strings *rndis_strings[] = { + &rndis_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static struct sk_buff *rndis_add_header(struct sk_buff *skb) +{ + skb = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); + if (skb) + rndis_add_hdr(skb); + return skb; +} + +static void rndis_response_available(void *_rndis) +{ + struct f_rndis *rndis = _rndis; + struct usb_request *req = rndis->notify_req; + struct usb_composite_dev *cdev = rndis->port.func.config->cdev; + __le32 *data = req->buf; + int status; + + if (atomic_inc_return(&rndis->notify_count)) + return; + + /* Send RNDIS RESPONSE_AVAILABLE notification; a + * USB_CDC_NOTIFY_RESPONSE_AVAILABLE "should" work too + * + * This is the only notification defined by RNDIS. + */ + data[0] = cpu_to_le32(1); + data[1] = cpu_to_le32(0); + + status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC); + if (status) { + atomic_dec(&rndis->notify_count); + DBG(cdev, "notify/0 --> %d\n", status); + } +} + +static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_rndis *rndis = req->context; + struct usb_composite_dev *cdev = rndis->port.func.config->cdev; + int status = req->status; + + /* after TX: + * - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control) + * - RNDIS_RESPONSE_AVAILABLE (status/irq) + */ + switch (status) { + case -ECONNRESET: + case -ESHUTDOWN: + /* connection gone */ + atomic_set(&rndis->notify_count, 0); + break; + default: + DBG(cdev, "RNDIS %s response error %d, %d/%d\n", + ep->name, status, + req->actual, req->length); + /* FALLTHROUGH */ + case 0: + if (ep != rndis->notify) + break; + + /* handle multiple pending RNDIS_RESPONSE_AVAILABLE + * notifications by resending until we're done + */ + if (atomic_dec_and_test(&rndis->notify_count)) + break; + status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC); + if (status) { + atomic_dec(&rndis->notify_count); + DBG(cdev, "notify/1 --> %d\n", status); + } + break; + } +} + +static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_rndis *rndis = req->context; + struct usb_composite_dev *cdev = rndis->port.func.config->cdev; + int status; + + /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ +// spin_lock(&dev->lock); + status = rndis_msg_parser(rndis->config, (u8 *) req->buf); + if (status < 0) + ERROR(cdev, "RNDIS command error %d, %d/%d\n", + status, req->actual, req->length); +// spin_unlock(&dev->lock); +} + +static int +rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) +{ + struct f_rndis *rndis = func_to_rndis(f); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + /* composite driver infrastructure handles everything except + * CDC class messages; interface activation uses set_alt(). + */ + switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { + + /* RNDIS uses the CDC command encapsulation mechanism to implement + * an RPC scheme, with much getting/setting of attributes by OID. + */ + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_SEND_ENCAPSULATED_COMMAND: + if (w_length > req->length || w_value + || w_index != rndis->ctrl_id) + goto invalid; + /* read the request; process it later */ + value = w_length; + req->complete = rndis_command_complete; + req->context = rndis; + /* later, rndis_response_available() sends a notification */ + break; + + case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_GET_ENCAPSULATED_RESPONSE: + if (w_value || w_index != rndis->ctrl_id) + goto invalid; + else { + u8 *buf; + u32 n; + + /* return the result */ + buf = rndis_get_next_response(rndis->config, &n); + if (buf) { + memcpy(req->buf, buf, n); + req->complete = rndis_response_complete; + rndis_free_response(rndis->config, buf); + value = n; + } + /* else stalls ... spec says to avoid that */ + } + break; + + default: +invalid: + VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; + req->length = value; + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(cdev, "rndis response on err %d\n", value); + } + + /* device either stalls (value < 0) or reports success */ + return value; +} + + +static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_rndis *rndis = func_to_rndis(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt == 0 */ + + if (intf == rndis->ctrl_id) { + if (rndis->notify->driver_data) { + VDBG(cdev, "reset rndis control %d\n", intf); + usb_ep_disable(rndis->notify); + } else { + VDBG(cdev, "init rndis ctrl %d\n", intf); + rndis->notify_desc = ep_choose(cdev->gadget, + rndis->hs.notify, + rndis->fs.notify); + } + usb_ep_enable(rndis->notify, rndis->notify_desc); + rndis->notify->driver_data = rndis; + + } else if (intf == rndis->data_id) { + struct net_device *net; + + if (rndis->port.in_ep->driver_data) { + DBG(cdev, "reset rndis\n"); + gether_disconnect(&rndis->port); + } else { + DBG(cdev, "init rndis\n"); + rndis->port.in = ep_choose(cdev->gadget, + rndis->hs.in, rndis->fs.in); + rndis->port.out = ep_choose(cdev->gadget, + rndis->hs.out, rndis->fs.out); + } + + /* Avoid ZLPs; they can be troublesome. */ + rndis->port.is_zlp_ok = false; + + /* RNDIS should be in the "RNDIS uninitialized" state, + * either never activated or after rndis_uninit(). + * + * We don't want data to flow here until a nonzero packet + * filter is set, at which point it enters "RNDIS data + * initialized" state ... but we do want the endpoints + * to be activated. It's a strange little state. + * + * REVISIT the RNDIS gadget code has done this wrong for a + * very long time. We need another call to the link layer + * code -- gether_updown(...bool) maybe -- to do it right. + */ + rndis->port.cdc_filter = 0; + + DBG(cdev, "RNDIS RX/TX early activation ... \n"); + net = gether_connect(&rndis->port); + if (IS_ERR(net)) + return PTR_ERR(net); + + rndis_set_param_dev(rndis->config, net, + &rndis->port.cdc_filter); + } else + goto fail; + + return 0; +fail: + return -EINVAL; +} + +static void rndis_disable(struct usb_function *f) +{ + struct f_rndis *rndis = func_to_rndis(f); + struct usb_composite_dev *cdev = f->config->cdev; + + if (!rndis->notify->driver_data) + return; + + DBG(cdev, "rndis deactivated\n"); + + rndis_uninit(rndis->config); + gether_disconnect(&rndis->port); + + usb_ep_disable(rndis->notify); + rndis->notify->driver_data = NULL; +} + +/*-------------------------------------------------------------------------*/ + +/* + * This isn't quite the same mechanism as CDC Ethernet, since the + * notification scheme passes less data, but the same set of link + * states must be tested. A key difference is that altsettings are + * not used to tell whether the link should send packets or not. + */ + +static void rndis_open(struct gether *geth) +{ + struct f_rndis *rndis = func_to_rndis(&geth->func); + struct usb_composite_dev *cdev = geth->func.config->cdev; + + DBG(cdev, "%s\n", __func__); + + rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, + bitrate(cdev->gadget) / 100); + rndis_signal_connect(rndis->config); +} + +static void rndis_close(struct gether *geth) +{ + struct f_rndis *rndis = func_to_rndis(&geth->func); + + DBG(geth->func.config->cdev, "%s\n", __func__); + + rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0); + rndis_signal_disconnect(rndis->config); +} + +/*-------------------------------------------------------------------------*/ + +/* ethernet function driver setup/binding */ + +static int __init +rndis_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_rndis *rndis = func_to_rndis(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs */ + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + rndis->ctrl_id = status; + + rndis_control_intf.bInterfaceNumber = status; + rndis_union_desc.bMasterInterface0 = status; + + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + rndis->data_id = status; + + rndis_data_intf.bInterfaceNumber = status; + rndis_union_desc.bSlaveInterface0 = status; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); + if (!ep) + goto fail; + rndis->port.in_ep = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc); + if (!ep) + goto fail; + rndis->port.out_ep = ep; + ep->driver_data = cdev; /* claim */ + + /* NOTE: a status/notification endpoint is, strictly speaking, + * optional. We don't treat it that way though! It's simpler, + * and some newer profiles don't treat it as optional. + */ + ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc); + if (!ep) + goto fail; + rndis->notify = ep; + ep->driver_data = cdev; /* claim */ + + status = -ENOMEM; + + /* allocate notification request and buffer */ + rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); + if (!rndis->notify_req) + goto fail; + rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL); + if (!rndis->notify_req->buf) + goto fail; + rndis->notify_req->length = STATUS_BYTECOUNT; + rndis->notify_req->context = rndis; + rndis->notify_req->complete = rndis_response_complete; + + /* copy descriptors, and track endpoint copies */ + f->descriptors = usb_copy_descriptors(eth_fs_function); + if (!f->descriptors) + goto fail; + + rndis->fs.in = usb_find_endpoint(eth_fs_function, + f->descriptors, &fs_in_desc); + rndis->fs.out = usb_find_endpoint(eth_fs_function, + f->descriptors, &fs_out_desc); + rndis->fs.notify = usb_find_endpoint(eth_fs_function, + f->descriptors, &fs_notify_desc); + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + hs_in_desc.bEndpointAddress = + fs_in_desc.bEndpointAddress; + hs_out_desc.bEndpointAddress = + fs_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->hs_descriptors = usb_copy_descriptors(eth_hs_function); + + if (!f->hs_descriptors) + goto fail; + + rndis->hs.in = usb_find_endpoint(eth_hs_function, + f->hs_descriptors, &hs_in_desc); + rndis->hs.out = usb_find_endpoint(eth_hs_function, + f->hs_descriptors, &hs_out_desc); + } + + rndis->port.open = rndis_open; + rndis->port.close = rndis_close; + + status = rndis_register(rndis_response_available, rndis); + if (status < 0) + goto fail; + rndis->config = status; + + rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0); + rndis_set_host_mac(rndis->config, rndis->ethaddr); + +#if 0 +// FIXME + if (rndis_set_param_vendor(rndis->config, vendorID, + manufacturer)) + goto fail0; +#endif + + /* NOTE: all that is done without knowing or caring about + * the network link ... which is unavailable to this code + * until we're activated via set_alt(). + */ + + DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n", + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + rndis->port.in_ep->name, rndis->port.out_ep->name, + rndis->notify->name); + return 0; + +fail: + if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors) + usb_free_descriptors(f->hs_descriptors); + if (f->descriptors) + usb_free_descriptors(f->descriptors); + + if (rndis->notify_req) { + kfree(rndis->notify_req->buf); + usb_ep_free_request(rndis->notify, rndis->notify_req); + } + + /* we might as well release our claims on endpoints */ + if (rndis->notify) + rndis->notify->driver_data = NULL; + if (rndis->port.out) + rndis->port.out_ep->driver_data = NULL; + if (rndis->port.in) + rndis->port.in_ep->driver_data = NULL; + + ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); + + return status; +} + +static void +rndis_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct f_rndis *rndis = func_to_rndis(f); + + rndis_deregister(rndis->config); + rndis_exit(); + + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + + kfree(rndis->notify_req->buf); + usb_ep_free_request(rndis->notify, rndis->notify_req); + + kfree(rndis); +} + +/* Some controllers can't support RNDIS ... */ +static inline bool can_support_rndis(struct usb_configuration *c) +{ + /* only two endpoints on sa1100 */ + if (gadget_is_sa1100(c->cdev->gadget)) + return false; + + /* everything else is *presumably* fine */ + return true; +} + +/** + * rndis_bind_config - add RNDIS network link to a configuration + * @c: the configuration to support the network link + * @ethaddr: a buffer in which the ethernet address of the host side + * side of the link was recorded + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gether_setup(). Caller is also responsible + * for calling @gether_cleanup() before module unload. + */ +int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +{ + struct f_rndis *rndis; + int status; + + if (!can_support_rndis(c) || !ethaddr) + return -EINVAL; + + /* maybe allocate device-global string IDs */ + if (rndis_string_defs[0].id == 0) { + + /* ... and setup RNDIS itself */ + status = rndis_init(); + if (status < 0) + return status; + + /* control interface label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + rndis_string_defs[0].id = status; + rndis_control_intf.iInterface = status; + + /* data interface label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + rndis_string_defs[1].id = status; + rndis_data_intf.iInterface = status; + } + + /* allocate and initialize one new instance */ + status = -ENOMEM; + rndis = kzalloc(sizeof *rndis, GFP_KERNEL); + if (!rndis) + goto fail; + + memcpy(rndis->ethaddr, ethaddr, ETH_ALEN); + + /* RNDIS activates when the host changes this filter */ + rndis->port.cdc_filter = 0; + + /* RNDIS has special (and complex) framing */ + rndis->port.header_len = sizeof(struct rndis_packet_msg_type); + rndis->port.wrap = rndis_add_header; + rndis->port.unwrap = rndis_rm_hdr; + + rndis->port.func.name = "rndis"; + rndis->port.func.strings = rndis_strings; + /* descriptors are per-instance copies */ + rndis->port.func.bind = rndis_bind; + rndis->port.func.unbind = rndis_unbind; + rndis->port.func.set_alt = rndis_set_alt; + rndis->port.func.setup = rndis_setup; + rndis->port.func.disable = rndis_disable; + + status = usb_add_function(c, &rndis->port.func); + if (status) { + kfree(rndis); +fail: + rndis_exit(); + } + return status; +} diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c new file mode 100644 index 000000000000..1b6bde9aaed5 --- /dev/null +++ b/drivers/usb/gadget/f_serial.c @@ -0,0 +1,296 @@ +/* + * f_serial.c - generic USB serial function driver + * + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 by David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * either version 2 of that License or (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/device.h> + +#include "u_serial.h" +#include "gadget_chips.h" + + +/* + * This function packages a simple "generic serial" port with no real + * control mechanisms, just raw data transfer over two bulk endpoints. + * + * Because it's not standardized, this isn't as interoperable as the + * CDC ACM driver. However, for many purposes it's just as functional + * if you can arrange appropriate host side drivers. + */ + +struct gser_descs { + struct usb_endpoint_descriptor *in; + struct usb_endpoint_descriptor *out; +}; + +struct f_gser { + struct gserial port; + u8 data_id; + u8 port_num; + + struct usb_descriptor_header **fs_function; + struct gser_descs fs; + struct usb_descriptor_header **hs_function; + struct gser_descs hs; +}; + +static inline struct f_gser *func_to_gser(struct usb_function *f) +{ + return container_of(f, struct f_gser, port.func); +} + +/*-------------------------------------------------------------------------*/ + +/* interface descriptor: */ + +static struct usb_interface_descriptor gser_interface_desc __initdata = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + /* .bInterfaceNumber = DYNAMIC */ + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *gser_fs_function[] __initdata = { + (struct usb_descriptor_header *) &gser_interface_desc, + (struct usb_descriptor_header *) &gser_fs_in_desc, + (struct usb_descriptor_header *) &gser_fs_out_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *gser_hs_function[] __initdata = { + (struct usb_descriptor_header *) &gser_interface_desc, + (struct usb_descriptor_header *) &gser_hs_in_desc, + (struct usb_descriptor_header *) &gser_hs_out_desc, + NULL, +}; + +/* string descriptors: */ + +static struct usb_string gser_string_defs[] = { + [0].s = "Generic Serial", + { } /* end of list */ +}; + +static struct usb_gadget_strings gser_string_table = { + .language = 0x0409, /* en-us */ + .strings = gser_string_defs, +}; + +static struct usb_gadget_strings *gser_strings[] = { + &gser_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_gser *gser = func_to_gser(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt == 0, so this is an activation or a reset */ + + if (gser->port.in->driver_data) { + DBG(cdev, "reset generic ttyGS%d\n", gser->port_num); + gserial_disconnect(&gser->port); + } else { + DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); + gser->port.in_desc = ep_choose(cdev->gadget, + gser->hs.in, gser->fs.in); + gser->port.out_desc = ep_choose(cdev->gadget, + gser->hs.out, gser->fs.out); + } + gserial_connect(&gser->port, gser->port_num); + return 0; +} + +static void gser_disable(struct usb_function *f) +{ + struct f_gser *gser = func_to_gser(f); + struct usb_composite_dev *cdev = f->config->cdev; + + DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num); + gserial_disconnect(&gser->port); +} + +/*-------------------------------------------------------------------------*/ + +/* serial function driver setup/binding */ + +static int __init +gser_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_gser *gser = func_to_gser(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs */ + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + gser->data_id = status; + gser_interface_desc.bInterfaceNumber = status; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc); + if (!ep) + goto fail; + gser->port.in = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc); + if (!ep) + goto fail; + gser->port.out = ep; + ep->driver_data = cdev; /* claim */ + + /* copy descriptors, and track endpoint copies */ + f->descriptors = usb_copy_descriptors(gser_fs_function); + + gser->fs.in = usb_find_endpoint(gser_fs_function, + f->descriptors, &gser_fs_in_desc); + gser->fs.out = usb_find_endpoint(gser_fs_function, + f->descriptors, &gser_fs_out_desc); + + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + gser_hs_in_desc.bEndpointAddress = + gser_fs_in_desc.bEndpointAddress; + gser_hs_out_desc.bEndpointAddress = + gser_fs_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->hs_descriptors = usb_copy_descriptors(gser_hs_function); + + gser->hs.in = usb_find_endpoint(gser_hs_function, + f->hs_descriptors, &gser_hs_in_desc); + gser->hs.out = usb_find_endpoint(gser_hs_function, + f->hs_descriptors, &gser_hs_out_desc); + } + + DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", + gser->port_num, + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + gser->port.in->name, gser->port.out->name); + return 0; + +fail: + /* we might as well release our claims on endpoints */ + if (gser->port.out) + gser->port.out->driver_data = NULL; + if (gser->port.in) + gser->port.in->driver_data = NULL; + + ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); + + return status; +} + +static void +gser_unbind(struct usb_configuration *c, struct usb_function *f) +{ + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + kfree(func_to_gser(f)); +} + +/** + * gser_bind_config - add a generic serial function to a configuration + * @c: the configuration to support the serial instance + * @port_num: /dev/ttyGS* port this interface will use + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gserial_setup() with enough ports to + * handle all the ones it binds. Caller is also responsible + * for calling @gserial_cleanup() before module unload. + */ +int __init gser_bind_config(struct usb_configuration *c, u8 port_num) +{ + struct f_gser *gser; + int status; + + /* REVISIT might want instance-specific strings to help + * distinguish instances ... + */ + + /* maybe allocate device-global string ID */ + if (gser_string_defs[0].id == 0) { + status = usb_string_id(c->cdev); + if (status < 0) + return status; + gser_string_defs[0].id = status; + } + + /* allocate and initialize one new instance */ + gser = kzalloc(sizeof *gser, GFP_KERNEL); + if (!gser) + return -ENOMEM; + + gser->port_num = port_num; + + gser->port.func.name = "gser"; + gser->port.func.strings = gser_strings; + gser->port.func.bind = gser_bind; + gser->port.func.unbind = gser_unbind; + gser->port.func.set_alt = gser_set_alt; + gser->port.func.disable = gser_disable; + + status = usb_add_function(c, &gser->port.func); + if (status) + kfree(gser); + return status; +} diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c new file mode 100644 index 000000000000..f18c3a14d72a --- /dev/null +++ b/drivers/usb/gadget/f_sourcesink.c @@ -0,0 +1,587 @@ +/* + * f_sourcesink.c - USB peripheral source/sink configuration driver + * + * Copyright (C) 2003-2008 David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/utsname.h> +#include <linux/device.h> + +#include "g_zero.h" +#include "gadget_chips.h" + + +/* + * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral + * controller drivers. + * + * This just sinks bulk packets OUT to the peripheral and sources them IN + * to the host, optionally with specific data patterns for integrity tests. + * As such it supports basic functionality and load tests. + * + * In terms of control messaging, this supports all the standard requests + * plus two that support control-OUT tests. If the optional "autoresume" + * mode is enabled, it provides good functional coverage for the "USBCV" + * test harness from USB-IF. + * + * Note that because this doesn't queue more than one request at a time, + * some other function must be used to test queueing logic. The network + * link (g_ether) is the best overall option for that, since its TX and RX + * queues are relatively independent, will receive a range of packet sizes, + * and can often be made to run out completely. Those issues are important + * when stress testing peripheral controller drivers. + * + * + * This is currently packaged as a configuration driver, which can't be + * combined with other functions to make composite devices. However, it + * can be combined with other independent configurations. + */ +struct f_sourcesink { + struct usb_function function; + + struct usb_ep *in_ep; + struct usb_ep *out_ep; + struct timer_list resume; +}; + +static inline struct f_sourcesink *func_to_ss(struct usb_function *f) +{ + return container_of(f, struct f_sourcesink, function); +} + +static unsigned autoresume; +module_param(autoresume, uint, 0); +MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); + +static unsigned pattern; +module_param(pattern, uint, 0); +MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); + +/*-------------------------------------------------------------------------*/ + +static struct usb_interface_descriptor source_sink_intf = { + .bLength = sizeof source_sink_intf, + .bDescriptorType = USB_DT_INTERFACE, + + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + /* .iInterface = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor fs_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor fs_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *fs_source_sink_descs[] = { + (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &fs_sink_desc, + (struct usb_descriptor_header *) &fs_source_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor hs_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor hs_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *hs_source_sink_descs[] = { + (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &hs_source_desc, + (struct usb_descriptor_header *) &hs_sink_desc, + NULL, +}; + +/* function-specific strings: */ + +static struct usb_string strings_sourcesink[] = { + [0].s = "source and sink data", + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_sourcesink = { + .language = 0x0409, /* en-us */ + .strings = strings_sourcesink, +}; + +static struct usb_gadget_strings *sourcesink_strings[] = { + &stringtab_sourcesink, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static void sourcesink_autoresume(unsigned long _c) +{ + struct usb_composite_dev *cdev = (void *)_c; + struct usb_gadget *g = cdev->gadget; + + /* Normally the host would be woken up for something + * more significant than just a timer firing; likely + * because of some direct user request. + */ + if (g->speed != USB_SPEED_UNKNOWN) { + int status = usb_gadget_wakeup(g); + DBG(cdev, "%s --> %d\n", __func__, status); + } +} + +static int __init +sourcesink_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_sourcesink *ss = func_to_ss(f); + int id; + + /* allocate interface ID(s) */ + id = usb_interface_id(c, f); + if (id < 0) + return id; + source_sink_intf.bInterfaceNumber = id; + + /* allocate endpoints */ + ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); + if (!ss->in_ep) { +autoconf_fail: + ERROR(cdev, "%s: can't autoconfigure on %s\n", + f->name, cdev->gadget->name); + return -ENODEV; + } + ss->in_ep->driver_data = cdev; /* claim */ + + ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc); + if (!ss->out_ep) + goto autoconf_fail; + ss->out_ep->driver_data = cdev; /* claim */ + + setup_timer(&ss->resume, sourcesink_autoresume, + (unsigned long) c->cdev); + + /* support high speed hardware */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + hs_source_desc.bEndpointAddress = + fs_source_desc.bEndpointAddress; + hs_sink_desc.bEndpointAddress = + fs_sink_desc.bEndpointAddress; + f->hs_descriptors = hs_source_sink_descs; + } + + DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + f->name, ss->in_ep->name, ss->out_ep->name); + return 0; +} + +static void +sourcesink_unbind(struct usb_configuration *c, struct usb_function *f) +{ + kfree(func_to_ss(f)); +} + +/* optionally require specific source/sink data patterns */ +static int check_read_data(struct f_sourcesink *ss, struct usb_request *req) +{ + unsigned i; + u8 *buf = req->buf; + struct usb_composite_dev *cdev = ss->function.config->cdev; + + for (i = 0; i < req->actual; i++, buf++) { + switch (pattern) { + + /* all-zeroes has no synchronization issues */ + case 0: + if (*buf == 0) + continue; + break; + + /* "mod63" stays in sync with short-terminated transfers, + * OR otherwise when host and gadget agree on how large + * each usb transfer request should be. Resync is done + * with set_interface or set_config. (We *WANT* it to + * get quickly out of sync if controllers or their drivers + * stutter for any reason, including buffer duplcation...) + */ + case 1: + if (*buf == (u8)(i % 63)) + continue; + break; + } + ERROR(cdev, "bad OUT byte, buf[%d] = %d\n", i, *buf); + usb_ep_set_halt(ss->out_ep); + return -EINVAL; + } + return 0; +} + +static void reinit_write_data(struct usb_ep *ep, struct usb_request *req) +{ + unsigned i; + u8 *buf = req->buf; + + switch (pattern) { + case 0: + memset(req->buf, 0, req->length); + break; + case 1: + for (i = 0; i < req->length; i++) + *buf++ = (u8) (i % 63); + break; + } +} + +static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_sourcesink *ss = ep->driver_data; + struct usb_composite_dev *cdev = ss->function.config->cdev; + int status = req->status; + + switch (status) { + + case 0: /* normal completion? */ + if (ep == ss->out_ep) { + check_read_data(ss, req); + memset(req->buf, 0x55, req->length); + } else + reinit_write_data(ep, req); + break; + + /* this endpoint is normally active while we're configured */ + case -ECONNABORTED: /* hardware forced ep reset */ + case -ECONNRESET: /* request dequeued */ + case -ESHUTDOWN: /* disconnect from host */ + VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status, + req->actual, req->length); + if (ep == ss->out_ep) + check_read_data(ss, req); + free_ep_req(ep, req); + return; + + case -EOVERFLOW: /* buffer overrun on read means that + * we didn't provide a big enough + * buffer. + */ + default: +#if 1 + DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name, + status, req->actual, req->length); +#endif + case -EREMOTEIO: /* short read */ + break; + } + + status = usb_ep_queue(ep, req, GFP_ATOMIC); + if (status) { + ERROR(cdev, "kill %s: resubmit %d bytes --> %d\n", + ep->name, req->length, status); + usb_ep_set_halt(ep); + /* FIXME recover later ... somehow */ + } +} + +static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in) +{ + struct usb_ep *ep; + struct usb_request *req; + int status; + + ep = is_in ? ss->in_ep : ss->out_ep; + req = alloc_ep_req(ep); + if (!req) + return -ENOMEM; + + req->complete = source_sink_complete; + if (is_in) + reinit_write_data(ep, req); + else + memset(req->buf, 0x55, req->length); + + status = usb_ep_queue(ep, req, GFP_ATOMIC); + if (status) { + struct usb_composite_dev *cdev; + + cdev = ss->function.config->cdev; + ERROR(cdev, "start %s %s --> %d\n", + is_in ? "IN" : "OUT", + ep->name, status); + free_ep_req(ep, req); + } + + return status; +} + +static void disable_source_sink(struct f_sourcesink *ss) +{ + struct usb_composite_dev *cdev; + + cdev = ss->function.config->cdev; + disable_endpoints(cdev, ss->in_ep, ss->out_ep); + del_timer(&ss->resume); + VDBG(cdev, "%s disabled\n", ss->function.name); +} + +static int +enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss) +{ + int result = 0; + const struct usb_endpoint_descriptor *src, *sink; + struct usb_ep *ep; + + src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc); + sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc); + + /* one endpoint writes (sources) zeroes IN (to the host) */ + ep = ss->in_ep; + result = usb_ep_enable(ep, src); + if (result < 0) + return result; + ep->driver_data = ss; + + result = source_sink_start_ep(ss, true); + if (result < 0) { +fail: + ep = ss->in_ep; + usb_ep_disable(ep); + ep->driver_data = NULL; + return result; + } + + /* one endpoint reads (sinks) anything OUT (from the host) */ + ep = ss->out_ep; + result = usb_ep_enable(ep, sink); + if (result < 0) + goto fail; + ep->driver_data = ss; + + result = source_sink_start_ep(ss, false); + if (result < 0) { + usb_ep_disable(ep); + ep->driver_data = NULL; + goto fail; + } + + DBG(cdev, "%s enabled\n", ss->function.name); + return result; +} + +static int sourcesink_set_alt(struct usb_function *f, + unsigned intf, unsigned alt) +{ + struct f_sourcesink *ss = func_to_ss(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt is zero */ + if (ss->in_ep->driver_data) + disable_source_sink(ss); + return enable_source_sink(cdev, ss); +} + +static void sourcesink_disable(struct usb_function *f) +{ + struct f_sourcesink *ss = func_to_ss(f); + + disable_source_sink(ss); +} + +static void sourcesink_suspend(struct usb_function *f) +{ + struct f_sourcesink *ss = func_to_ss(f); + struct usb_composite_dev *cdev = f->config->cdev; + + if (cdev->gadget->speed == USB_SPEED_UNKNOWN) + return; + + if (autoresume) { + mod_timer(&ss->resume, jiffies + (HZ * autoresume)); + DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); + } else + DBG(cdev, "%s\n", __func__); +} + +static void sourcesink_resume(struct usb_function *f) +{ + struct f_sourcesink *ss = func_to_ss(f); + struct usb_composite_dev *cdev = f->config->cdev; + + DBG(cdev, "%s\n", __func__); + del_timer(&ss->resume); +} + +/*-------------------------------------------------------------------------*/ + +static int __init sourcesink_bind_config(struct usb_configuration *c) +{ + struct f_sourcesink *ss; + int status; + + ss = kzalloc(sizeof *ss, GFP_KERNEL); + if (!ss) + return -ENOMEM; + + ss->function.name = "source/sink"; + ss->function.descriptors = fs_source_sink_descs; + ss->function.bind = sourcesink_bind; + ss->function.unbind = sourcesink_unbind; + ss->function.set_alt = sourcesink_set_alt; + ss->function.disable = sourcesink_disable; + ss->function.suspend = sourcesink_suspend; + ss->function.resume = sourcesink_resume; + + status = usb_add_function(c, &ss->function); + if (status) + kfree(ss); + return status; +} + +static int sourcesink_setup(struct usb_configuration *c, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_request *req = c->cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + /* composite driver infrastructure handles everything except + * the two control test requests. + */ + switch (ctrl->bRequest) { + + /* + * These are the same vendor-specific requests supported by + * Intel's USB 2.0 compliance test devices. We exceed that + * device spec by allowing multiple-packet requests. + * + * NOTE: the Control-OUT data stays in req->buf ... better + * would be copying it into a scratch buffer, so that other + * requests may safely intervene. + */ + case 0x5b: /* control WRITE test -- fill the buffer */ + if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) + goto unknown; + if (w_value || w_index) + break; + /* just read that many bytes into the buffer */ + if (w_length > req->length) + break; + value = w_length; + break; + case 0x5c: /* control READ test -- return the buffer */ + if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) + goto unknown; + if (w_value || w_index) + break; + /* expect those bytes are still in the buffer; send back */ + if (w_length > req->length) + break; + value = w_length; + break; + + default: +unknown: + VDBG(c->cdev, + "unknown control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; + req->length = value; + value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(c->cdev, "source/sinkc response, err %d\n", + value); + } + + /* device either stalls (value < 0) or reports success */ + return value; +} + +static struct usb_configuration sourcesink_driver = { + .label = "source/sink", + .strings = sourcesink_strings, + .bind = sourcesink_bind_config, + .setup = sourcesink_setup, + .bConfigurationValue = 3, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* 2 mA, minimal */ + /* .iConfiguration = DYNAMIC */ +}; + +/** + * sourcesink_add - add a source/sink testing configuration to a device + * @cdev: the device to support the configuration + */ +int __init sourcesink_add(struct usb_composite_dev *cdev) +{ + int id; + + /* allocate string ID(s) */ + id = usb_string_id(cdev); + if (id < 0) + return id; + strings_sourcesink[0].id = id; + + source_sink_intf.iInterface = id; + sourcesink_driver.iConfiguration = id; + + /* support autoresume for remote wakeup testing */ + if (autoresume) + sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + + /* support OTG systems */ + if (gadget_is_otg(cdev->gadget)) { + sourcesink_driver.descriptors = otg_desc; + sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + return usb_add_config(cdev, &sourcesink_driver); +} diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c new file mode 100644 index 000000000000..afeab9a0523f --- /dev/null +++ b/drivers/usb/gadget/f_subset.c @@ -0,0 +1,423 @@ +/* + * f_subset.c -- "CDC Subset" Ethernet link function driver + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/etherdevice.h> + +#include "u_ether.h" + + +/* + * This function packages a simple "CDC Subset" Ethernet port with no real + * control mechanisms; just raw data transfer over two bulk endpoints. + * The data transfer model is exactly that of CDC Ethernet, which is + * why we call it the "CDC Subset". + * + * Because it's not standardized, this has some interoperability issues. + * They mostly relate to driver binding, since the data transfer model is + * so simple (CDC Ethernet). The original versions of this protocol used + * specific product/vendor IDs: byteswapped IDs for Digital Equipment's + * SA-1100 "Itsy" board, which could run Linux 2.4 kernels and supported + * daughtercards with USB peripheral connectors. (It was used more often + * with other boards, using the Itsy identifiers.) Linux hosts recognized + * this with CONFIG_USB_ARMLINUX; these devices have only one configuration + * and one interface. + * + * At some point, MCCI defined a (nonconformant) CDC MDLM variant called + * "SAFE", which happens to have a mode which is identical to the "CDC + * Subset" in terms of data transfer and lack of control model. This was + * adopted by later Sharp Zaurus models, and by some other software which + * Linux hosts recognize with CONFIG_USB_NET_ZAURUS. + * + * Because Microsoft's RNDIS drivers are far from robust, we added a few + * descriptors to the CDC Subset code, making this code look like a SAFE + * implementation. This lets you use MCCI's host side MS-Windows drivers + * if you get fed up with RNDIS. It also makes it easier for composite + * drivers to work, since they can use class based binding instead of + * caring about specific product and vendor IDs. + */ + +struct geth_descs { + struct usb_endpoint_descriptor *in; + struct usb_endpoint_descriptor *out; +}; + +struct f_gether { + struct gether port; + + char ethaddr[14]; + + struct usb_descriptor_header **fs_function; + struct geth_descs fs; + struct usb_descriptor_header **hs_function; + struct geth_descs hs; +}; + +static inline struct f_gether *func_to_geth(struct usb_function *f) +{ + return container_of(f, struct f_gether, port.func); +} + +/*-------------------------------------------------------------------------*/ + +/* + * "Simple" CDC-subset option is a simple vendor-neutral model that most + * full speed controllers can handle: one interface, two bulk endpoints. + * To assist host side drivers, we fancy it up a bit, and add descriptors so + * some host side drivers will understand it as a "SAFE" variant. + * + * "SAFE" loosely follows CDC WMC MDLM, violating the spec in various ways. + * Data endpoints live in the control interface, there's no data interface. + * And it's not used to talk to a cell phone radio. + */ + +/* interface descriptor: */ + +static struct usb_interface_descriptor subset_data_intf __initdata = { + .bLength = sizeof subset_data_intf, + .bDescriptorType = USB_DT_INTERFACE, + + /* .bInterfaceNumber = DYNAMIC */ + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_cdc_header_desc header_desc __initdata = { + .bLength = sizeof header_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + + .bcdCDC = __constant_cpu_to_le16(0x0110), +}; + +static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { + .bLength = sizeof mdlm_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_MDLM_TYPE, + + .bcdVersion = __constant_cpu_to_le16(0x0100), + .bGUID = { + 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, + 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, + }, +}; + +/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we + * can't really use its struct. All we do here is say that we're using + * the submode of "SAFE" which directly matches the CDC Subset. + */ +static u8 mdlm_detail_desc[] __initdata = { + 6, + USB_DT_CS_INTERFACE, + USB_CDC_MDLM_DETAIL_TYPE, + + 0, /* "SAFE" */ + 0, /* network control capabilities (none) */ + 0, /* network data capabilities ("raw" encapsulation) */ +}; + +static struct usb_cdc_ether_desc ether_desc __initdata = { + .bLength = sizeof ether_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, + + /* this descriptor actually adds value, surprise! */ + /* .iMACAddress = DYNAMIC */ + .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = __constant_cpu_to_le16(0), + .bNumberPowerFilters = 0, +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor fs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor fs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *fs_eth_function[] __initdata = { + (struct usb_descriptor_header *) &subset_data_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &mdlm_desc, + (struct usb_descriptor_header *) &mdlm_detail_desc, + (struct usb_descriptor_header *) ðer_desc, + (struct usb_descriptor_header *) &fs_in_desc, + (struct usb_descriptor_header *) &fs_out_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor hs_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor hs_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *hs_eth_function[] __initdata = { + (struct usb_descriptor_header *) &subset_data_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &mdlm_desc, + (struct usb_descriptor_header *) &mdlm_detail_desc, + (struct usb_descriptor_header *) ðer_desc, + (struct usb_descriptor_header *) &hs_in_desc, + (struct usb_descriptor_header *) &hs_out_desc, + NULL, +}; + +/* string descriptors: */ + +static struct usb_string geth_string_defs[] = { + [0].s = "CDC Ethernet Subset/SAFE", + [1].s = NULL /* DYNAMIC */, + { } /* end of list */ +}; + +static struct usb_gadget_strings geth_string_table = { + .language = 0x0409, /* en-us */ + .strings = geth_string_defs, +}; + +static struct usb_gadget_strings *geth_strings[] = { + &geth_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_gether *geth = func_to_geth(f); + struct usb_composite_dev *cdev = f->config->cdev; + struct net_device *net; + + /* we know alt == 0, so this is an activation or a reset */ + + if (geth->port.in_ep->driver_data) { + DBG(cdev, "reset cdc subset\n"); + gether_disconnect(&geth->port); + } + + DBG(cdev, "init + activate cdc subset\n"); + geth->port.in = ep_choose(cdev->gadget, + geth->hs.in, geth->fs.in); + geth->port.out = ep_choose(cdev->gadget, + geth->hs.out, geth->fs.out); + + net = gether_connect(&geth->port); + return IS_ERR(net) ? PTR_ERR(net) : 0; +} + +static void geth_disable(struct usb_function *f) +{ + struct f_gether *geth = func_to_geth(f); + struct usb_composite_dev *cdev = f->config->cdev; + + DBG(cdev, "net deactivated\n"); + gether_disconnect(&geth->port); +} + +/*-------------------------------------------------------------------------*/ + +/* serial function driver setup/binding */ + +static int __init +geth_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_gether *geth = func_to_geth(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs */ + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + subset_data_intf.bInterfaceNumber = status; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); + if (!ep) + goto fail; + geth->port.in_ep = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc); + if (!ep) + goto fail; + geth->port.out_ep = ep; + ep->driver_data = cdev; /* claim */ + + /* copy descriptors, and track endpoint copies */ + f->descriptors = usb_copy_descriptors(fs_eth_function); + + geth->fs.in = usb_find_endpoint(fs_eth_function, + f->descriptors, &fs_in_desc); + geth->fs.out = usb_find_endpoint(fs_eth_function, + f->descriptors, &fs_out_desc); + + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + hs_in_desc.bEndpointAddress = + fs_in_desc.bEndpointAddress; + hs_out_desc.bEndpointAddress = + fs_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->hs_descriptors = usb_copy_descriptors(hs_eth_function); + + geth->hs.in = usb_find_endpoint(hs_eth_function, + f->hs_descriptors, &hs_in_desc); + geth->hs.out = usb_find_endpoint(hs_eth_function, + f->hs_descriptors, &hs_out_desc); + } + + /* NOTE: all that is done without knowing or caring about + * the network link ... which is unavailable to this code + * until we're activated via set_alt(). + */ + + DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n", + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + geth->port.in_ep->name, geth->port.out_ep->name); + return 0; + +fail: + /* we might as well release our claims on endpoints */ + if (geth->port.out) + geth->port.out_ep->driver_data = NULL; + if (geth->port.in) + geth->port.in_ep->driver_data = NULL; + + ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); + + return status; +} + +static void +geth_unbind(struct usb_configuration *c, struct usb_function *f) +{ + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + geth_string_defs[1].s = NULL; + kfree(func_to_geth(f)); +} + +/** + * geth_bind_config - add CDC Subset network link to a configuration + * @c: the configuration to support the network link + * @ethaddr: a buffer in which the ethernet address of the host side + * side of the link was recorded + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gether_setup(). Caller is also responsible + * for calling @gether_cleanup() before module unload. + */ +int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +{ + struct f_gether *geth; + int status; + + if (!ethaddr) + return -EINVAL; + + /* maybe allocate device-global string IDs */ + if (geth_string_defs[0].id == 0) { + + /* interface label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + geth_string_defs[0].id = status; + subset_data_intf.iInterface = status; + + /* MAC address */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + geth_string_defs[1].id = status; + ether_desc.iMACAddress = status; + } + + /* allocate and initialize one new instance */ + geth = kzalloc(sizeof *geth, GFP_KERNEL); + if (!geth) + return -ENOMEM; + + /* export host's Ethernet address in CDC format */ + snprintf(geth->ethaddr, sizeof geth->ethaddr, + "%02X%02X%02X%02X%02X%02X", + ethaddr[0], ethaddr[1], ethaddr[2], + ethaddr[3], ethaddr[4], ethaddr[5]); + geth_string_defs[1].s = geth->ethaddr; + + geth->port.cdc_filter = DEFAULT_FILTER; + + geth->port.func.name = "cdc_subset"; + geth->port.func.strings = geth_strings; + geth->port.func.bind = geth_bind; + geth->port.func.unbind = geth_unbind; + geth->port.func.set_alt = geth_set_alt; + geth->port.func.disable = geth_disable; + + status = usb_add_function(c, &geth->port.func); + if (status) { + geth_string_defs[1].s = NULL; + kfree(geth); + } + return status; +} diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 47bb9f09a1aa..15c24edbb61a 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3867,8 +3867,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) curlun->dev.parent = &gadget->dev; curlun->dev.driver = &fsg_driver.driver; dev_set_drvdata(&curlun->dev, fsg); - snprintf(curlun->dev.bus_id, BUS_ID_SIZE, - "%s-lun%d", gadget->dev.bus_id, i); + dev_set_name(&curlun->dev,"%s-lun%d", + dev_name(&gadget->dev), i); if ((rc = device_register(&curlun->dev)) != 0) { INFO(fsg, "failed to register LUN%d: %d\n", i, rc); diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 18687543d7fa..1695382f30fe 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -2331,7 +2331,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) udc_controller->gadget.name = driver_name; /* Setup gadget.dev and register with kernel */ - strcpy(udc_controller->gadget.dev.bus_id, "gadget"); + dev_set_name(&udc_controller->gadget.dev, "gadget"); udc_controller->gadget.dev.release = fsl_udc_release; udc_controller->gadget.dev.parent = &pdev->dev; ret = device_register(&udc_controller->gadget.dev); diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h new file mode 100644 index 000000000000..dd2f16ad5a88 --- /dev/null +++ b/drivers/usb/gadget/g_zero.h @@ -0,0 +1,25 @@ +/* + * This header declares the utility functions used by "Gadget Zero", plus + * interfaces to its two single-configuration function drivers. + */ + +#ifndef __G_ZERO_H +#define __G_ZERO_H + +#include <linux/usb/composite.h> + +/* global state */ +extern unsigned buflen; +extern const struct usb_descriptor_header *otg_desc[]; + +/* common utilities */ +struct usb_request *alloc_ep_req(struct usb_ep *ep); +void free_ep_req(struct usb_ep *ep, struct usb_request *req); +void disable_endpoints(struct usb_composite_dev *cdev, + struct usb_ep *in, struct usb_ep *out); + +/* configuration-specific linkup */ +int sourcesink_add(struct usb_composite_dev *cdev); +int loopback_add(struct usb_composite_dev *cdev); + +#endif /* __G_ZERO_H */ diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index ca5149ea7312..5246e8fef2b2 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -214,3 +214,26 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x21; return -ENOENT; } + + +/** + * gadget_supports_altsettings - return true if altsettings work + * @gadget: the gadget in question + */ +static inline bool gadget_supports_altsettings(struct usb_gadget *gadget) +{ + /* PXA 21x/25x/26x has no altsettings at all */ + if (gadget_is_pxa(gadget)) + return false; + + /* PXA 27x and 3xx have *broken* altsetting support */ + if (gadget_is_pxa27x(gadget)) + return false; + + /* SH3 hardware just doesn't do altsettings */ + if (gadget_is_sh(gadget)) + return false; + + /* Everything else is *presumably* fine ... */ + return true; +} diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index be6613afedbf..48f1c63b7013 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1790,7 +1790,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.ops = &goku_ops; /* the "gadget" abstracts/virtualizes the controller */ - strcpy(dev->gadget.dev.bus_id, "gadget"); + dev_set_name(&dev->gadget.dev, "gadget"); dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index f132a9219e11..04692d59fc1c 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -32,6 +32,7 @@ #include <asm/uaccess.h> #include <linux/slab.h> #include <linux/poll.h> +#include <linux/smp_lock.h> #include <linux/device.h> #include <linux/moduleparam.h> @@ -483,8 +484,7 @@ ep_release (struct inode *inode, struct file *fd) return 0; } -static int ep_ioctl (struct inode *inode, struct file *fd, - unsigned code, unsigned long value) +static long ep_ioctl(struct file *fd, unsigned code, unsigned long value) { struct ep_data *data = fd->private_data; int status; @@ -740,7 +740,7 @@ static const struct file_operations ep_io_operations = { .read = ep_read, .write = ep_write, - .ioctl = ep_ioctl, + .unlocked_ioctl = ep_ioctl, .release = ep_release, .aio_read = ep_aio_read, @@ -1294,15 +1294,18 @@ out: return mask; } -static int dev_ioctl (struct inode *inode, struct file *fd, - unsigned code, unsigned long value) +static long dev_ioctl (struct file *fd, unsigned code, unsigned long value) { struct dev_data *dev = fd->private_data; struct usb_gadget *gadget = dev->gadget; + long ret = -ENOTTY; - if (gadget->ops->ioctl) - return gadget->ops->ioctl (gadget, code, value); - return -ENOTTY; + if (gadget->ops->ioctl) { + lock_kernel(); + ret = gadget->ops->ioctl (gadget, code, value); + unlock_kernel(); + } + return ret; } /* used after device configuration */ @@ -1314,7 +1317,7 @@ static const struct file_operations ep0_io_operations = { .write = ep0_write, .fasync = ep0_fasync, .poll = ep0_poll, - .ioctl = dev_ioctl, + .unlocked_ioctl = dev_ioctl, .release = dev_release, }; @@ -1964,7 +1967,7 @@ static const struct file_operations dev_init_operations = { .open = dev_open, .write = dev_config, .fasync = ep0_fasync, - .ioctl = dev_ioctl, + .unlocked_ioctl = dev_ioctl, .release = dev_release, }; diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 825abd2621b3..c6e7df04c69a 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = { static void nop_release(struct device *dev) { - DEBUG("%s %s\n", __func__, dev->bus_id); + DEBUG("%s %s\n", __func__, dev_name(dev)); } static struct lh7a40x_udc memory = { diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index ee6b35fa870f..8da7535c0c70 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1593,7 +1593,7 @@ static int __init m66592_probe(struct platform_device *pdev) m66592->gadget.ops = &m66592_gadget_ops; device_initialize(&m66592->gadget.dev); - strcpy(m66592->gadget.dev.bus_id, "gadget"); + dev_set_name(&m66592->gadget, "gadget"); m66592->gadget.is_dualspeed = 1; m66592->gadget.dev.parent = &pdev->dev; m66592->gadget.dev.dma_mask = pdev->dev.dma_mask; diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h index 09e3ee4eeae1..df886cec5ef4 100644 --- a/drivers/usb/gadget/ndis.h +++ b/drivers/usb/gadget/ndis.h @@ -1,11 +1,11 @@ /* - * ndis.h - * + * ndis.h + * * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de> - * - * Thanks to the cygwin development team, + * + * Thanks to the cygwin development team, * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net> - * + * * THIS SOFTWARE IS NOT COPYRIGHTED * * This source code is offered for use in the public domain. You may diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index e01862300169..b67ab677af72 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2768,7 +2768,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.is_dualspeed = 1; /* the "gadget" abstracts/virtualizes the controller */ - strcpy (dev->gadget.dev.bus_id, "gadget"); + dev_set_name(&dev->gadget.dev, "gadget"); dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 03a7f49d207d..4b79a8509e84 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2686,7 +2686,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) udc->gadget.name = driver_name; device_initialize(&udc->gadget.dev); - strcpy (udc->gadget.dev.bus_id, "gadget"); + dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.dev.release = omap_udc_release; udc->gadget.dev.parent = &odev->dev; if (use_dma) diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index ec8f2eb041ca..49cd9e145a9b 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -828,9 +828,8 @@ printer_poll(struct file *fd, poll_table *wait) return status; } -static int -printer_ioctl(struct inode *inode, struct file *fd, unsigned int code, - unsigned long arg) +static long +printer_ioctl(struct file *fd, unsigned int code, unsigned long arg) { struct printer_dev *dev = fd->private_data; unsigned long flags; @@ -869,7 +868,7 @@ static struct file_operations printer_io_operations = { .write = printer_write, .fsync = printer_fsync, .poll = printer_poll, - .ioctl = printer_ioctl, + .unlocked_ioctl = printer_ioctl, .release = printer_close }; @@ -1361,8 +1360,8 @@ printer_bind(struct usb_gadget *gadget) /* Setup the sysfs files for the printer gadget. */ - dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, - "g_printer"); + dev->pdev = device_create_drvdata(usb_gadget_class, NULL, + g_printer_devno, NULL, "g_printer"); if (IS_ERR(dev->pdev)) { ERROR(dev, "Failed to create device: g_printer\n"); goto fail; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 031dceb93023..8fb0066609bb 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -152,9 +152,10 @@ static int is_vbus_present(void) static void pullup_off(void) { struct pxa2xx_udc_mach_info *mach = the_controller->mach; + int off_level = mach->gpio_pullup_inverted; if (mach->gpio_pullup) - gpio_set_value(mach->gpio_pullup, 0); + gpio_set_value(mach->gpio_pullup, off_level); else if (mach->udc_command) mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); } @@ -162,9 +163,10 @@ static void pullup_off(void) static void pullup_on(void) { struct pxa2xx_udc_mach_info *mach = the_controller->mach; + int on_level = !mach->gpio_pullup_inverted; if (mach->gpio_pullup) - gpio_set_value(mach->gpio_pullup, 1); + gpio_set_value(mach->gpio_pullup, on_level); else if (mach->udc_command) mach->udc_command(PXA2XX_UDC_CMD_CONNECT); } @@ -1818,7 +1820,7 @@ pxa25x_udc_irq(int irq, void *_dev) static void nop_release (struct device *dev) { - DMSG("%s %s\n", __func__, dev->bus_id); + DMSG("%s %s\n", __func__, dev_name(dev)); } /* this uses load-time allocation and initialization (instead of diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 9c0e82ec5c43..9d447d8cfc0c 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1575,7 +1575,6 @@ static void udc_enable(struct pxa_udc *udc) { udc_writel(udc, UDCICR0, 0); udc_writel(udc, UDCICR1, 0); - udc_writel(udc, UP2OCR, UP2OCR_HXOE); udc_clear_mask_UDCCR(udc, UDCCR_UDE); clk_enable(udc->clk); diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index d0677f5d3cd5..7228e8562236 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -1,8 +1,6 @@ /* * RNDIS MSG parser * - * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $ - * * Authors: Benedikt Spranger, Pengutronix * Robert Schwebel, Pengutronix * @@ -30,6 +28,7 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/netdevice.h> #include <asm/io.h> @@ -38,9 +37,7 @@ #include <asm/unaligned.h> -#undef RNDIS_PM -#undef RNDIS_WAKEUP -#undef VERBOSE +#undef VERBOSE_DEBUG #include "rndis.h" @@ -96,9 +93,6 @@ static const u32 oid_supported_list [] = OID_GEN_MAXIMUM_TOTAL_SIZE, OID_GEN_MEDIA_CONNECT_STATUS, OID_GEN_PHYSICAL_MEDIUM, -#if 0 - OID_GEN_RNDIS_CONFIG_PARAMETER, -#endif /* the statistical stuff */ OID_GEN_XMIT_OK, @@ -146,7 +140,14 @@ static const u32 oid_supported_list [] = #endif /* RNDIS_OPTIONAL_STATS */ #ifdef RNDIS_PM - /* PM and wakeup are mandatory for USB: */ + /* PM and wakeup are "mandatory" for USB, but the RNDIS specs + * don't say what they mean ... and the NDIS specs are often + * confusing and/or ambiguous in this context. (That is, more + * so than their specs for the other OIDs.) + * + * FIXME someone who knows what these should do, please + * implement them! + */ /* power management */ OID_PNP_CAPABILITIES, @@ -173,6 +174,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, __le32 *outbuf; int i, count; rndis_query_cmplt_type *resp; + struct net_device *net; + struct net_device_stats *stats; if (!r) return -ENOMEM; resp = (rndis_query_cmplt_type *) r->buf; @@ -194,6 +197,12 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, outbuf = (__le32 *) &resp[1]; resp->InformationBufferOffset = __constant_cpu_to_le32 (16); + net = rndis_per_dev_params[configNr].dev; + if (net->get_stats) + stats = net->get_stats(net); + else + stats = NULL; + switch (OID) { /* general oids (table 4-1) */ @@ -350,11 +359,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_GEN_XMIT_OK: if (rndis_debug > 1) DBG("%s: OID_GEN_XMIT_OK\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].stats->tx_packets - - rndis_per_dev_params [configNr].stats->tx_errors - - rndis_per_dev_params [configNr].stats->tx_dropped); + if (stats) { + *outbuf = cpu_to_le32(stats->tx_packets + - stats->tx_errors - stats->tx_dropped); retval = 0; } break; @@ -363,11 +370,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_GEN_RCV_OK: if (rndis_debug > 1) DBG("%s: OID_GEN_RCV_OK\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].stats->rx_packets - - rndis_per_dev_params [configNr].stats->rx_errors - - rndis_per_dev_params [configNr].stats->rx_dropped); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_packets + - stats->rx_errors - stats->rx_dropped); retval = 0; } break; @@ -376,9 +381,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_GEN_XMIT_ERROR: if (rndis_debug > 1) DBG("%s: OID_GEN_XMIT_ERROR\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->tx_errors); + if (stats) { + *outbuf = cpu_to_le32(stats->tx_errors); retval = 0; } break; @@ -387,9 +391,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_GEN_RCV_ERROR: if (rndis_debug > 1) DBG("%s: OID_GEN_RCV_ERROR\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->rx_errors); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_errors); retval = 0; } break; @@ -397,150 +400,12 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_RCV_NO_BUFFER: DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->rx_dropped); - retval = 0; - } - break; - -#ifdef RNDIS_OPTIONAL_STATS - case OID_GEN_DIRECTED_BYTES_XMIT: - DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__); - /* - * Aunt Tilly's size of shoes - * minus antarctica count of penguins - * divided by weight of Alpha Centauri - */ - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 ( - (rndis_per_dev_params [configNr] - .stats->tx_packets - - rndis_per_dev_params [configNr] - .stats->tx_errors - - rndis_per_dev_params [configNr] - .stats->tx_dropped) - * 123); - retval = 0; - } - break; - - case OID_GEN_DIRECTED_FRAMES_XMIT: - DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__); - /* dito */ - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 ( - (rndis_per_dev_params [configNr] - .stats->tx_packets - - rndis_per_dev_params [configNr] - .stats->tx_errors - - rndis_per_dev_params [configNr] - .stats->tx_dropped) - / 123); - retval = 0; - } - break; - - case OID_GEN_MULTICAST_BYTES_XMIT: - DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->multicast*1234); - retval = 0; - } - break; - - case OID_GEN_MULTICAST_FRAMES_XMIT: - DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->multicast); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_BYTES_XMIT: - DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->tx_packets/42*255); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_FRAMES_XMIT: - DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->tx_packets/42); - retval = 0; - } - break; - - case OID_GEN_DIRECTED_BYTES_RCV: - DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__); - *outbuf = __constant_cpu_to_le32 (0); - retval = 0; - break; - - case OID_GEN_DIRECTED_FRAMES_RCV: - DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__); - *outbuf = __constant_cpu_to_le32 (0); - retval = 0; - break; - - case OID_GEN_MULTICAST_BYTES_RCV: - DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->multicast * 1111); - retval = 0; - } - break; - - case OID_GEN_MULTICAST_FRAMES_RCV: - DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->multicast); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_BYTES_RCV: - DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->rx_packets/42*255); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_FRAMES_RCV: - DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->rx_packets/42); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_dropped); retval = 0; } break; - case OID_GEN_RCV_CRC_ERROR: - DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->rx_crc_errors); - retval = 0; - } - break; - - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__); - *outbuf = __constant_cpu_to_le32 (0); - retval = 0; - break; -#endif /* RNDIS_OPTIONAL_STATS */ - /* ieee802.3 OIDs (table 4-3) */ /* mandatory */ @@ -592,9 +457,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_RCV_ERROR_ALIGNMENT: DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__); - if (rndis_per_dev_params [configNr].stats) { - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] - .stats->rx_frame_errors); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_frame_errors); retval = 0; } break; @@ -613,64 +477,6 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; break; -#ifdef RNDIS_OPTIONAL_STATS - case OID_802_3_XMIT_DEFERRED: - DBG("%s: OID_802_3_XMIT_DEFERRED\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_MAX_COLLISIONS: - DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__); - /* TODO */ - break; - - case OID_802_3_RCV_OVERRUN: - DBG("%s: OID_802_3_RCV_OVERRUN\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_UNDERRUN: - DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_HEARTBEAT_FAILURE: - DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_TIMES_CRS_LOST: - DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_LATE_COLLISIONS: - DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__); - /* TODO */ - break; -#endif /* RNDIS_OPTIONAL_STATS */ - -#ifdef RNDIS_PM - /* power management OIDs (table 4-5) */ - case OID_PNP_CAPABILITIES: - DBG("%s: OID_PNP_CAPABILITIES\n", __func__); - - /* for now, no wakeup capabilities */ - length = sizeof (struct NDIS_PNP_CAPABILITIES); - memset(outbuf, 0, length); - retval = 0; - break; - case OID_PNP_QUERY_POWER: - DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__, - get_unaligned_le32(buf) - 1); - /* only suspend is a real power state, and - * it can't be entered by OID_PNP_SET_POWER... - */ - length = 0; - retval = 0; - break; -#endif - default: pr_warning("%s: query unknown OID 0x%08X\n", __func__, OID); @@ -726,9 +532,6 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, * what makes the packet flow start and stop, like * activating the CDC Ethernet altsetting. */ -#ifdef RNDIS_PM -update_linkstate: -#endif retval = 0; if (*params->filter) { params->state = RNDIS_DATA_INITIALIZED; @@ -747,49 +550,6 @@ update_linkstate: DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__); retval = 0; break; -#if 0 - case OID_GEN_RNDIS_CONFIG_PARAMETER: - { - struct rndis_config_parameter *param; - param = (struct rndis_config_parameter *) buf; - DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n", - __func__, - min(cpu_to_le32(param->ParameterNameLength),80), - buf + param->ParameterNameOffset); - retval = 0; - } - break; -#endif - -#ifdef RNDIS_PM - case OID_PNP_SET_POWER: - /* The only real power state is USB suspend, and RNDIS requests - * can't enter it; this one isn't really about power. After - * resuming, Windows forces a reset, and then SET_POWER D0. - * FIXME ... then things go batty; Windows wedges itself. - */ - i = get_unaligned_le32(buf); - DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1); - switch (i) { - case NdisDeviceStateD0: - *params->filter = params->saved_filter; - goto update_linkstate; - case NdisDeviceStateD3: - case NdisDeviceStateD2: - case NdisDeviceStateD1: - params->saved_filter = *params->filter; - retval = 0; - break; - } - break; - -#ifdef RNDIS_WAKEUP - // no wakeup support advertised, so wakeup OIDs always fail: - // - OID_PNP_ENABLE_WAKE_UP - // - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN -#endif - -#endif /* RNDIS_PM */ default: pr_warning("%s: set unknown OID 0x%08X, size %d\n", @@ -807,8 +567,10 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) { rndis_init_cmplt_type *resp; rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; - if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; + if (!params->dev) + return -ENOTSUPP; r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); if (!r) @@ -826,7 +588,7 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3); resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1); resp->MaxTransferSize = cpu_to_le32 ( - rndis_per_dev_params [configNr].dev->mtu + params->dev->mtu + sizeof (struct ethhdr) + sizeof (struct rndis_packet_msg_type) + 22); @@ -834,10 +596,7 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) resp->AFListOffset = __constant_cpu_to_le32 (0); resp->AFListSize = __constant_cpu_to_le32 (0); - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + params->resp_avail(params->v); return 0; } @@ -845,9 +604,11 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) { rndis_query_cmplt_type *resp; rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; // DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); - if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; + if (!params->dev) + return -ENOTSUPP; /* * we need more memory: @@ -878,9 +639,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) } else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + params->resp_avail(params->v); return 0; } @@ -889,6 +648,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) u32 BufLength, BufOffset; rndis_set_cmplt_type *resp; rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); if (!r) @@ -898,7 +658,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) BufLength = le32_to_cpu (buf->InformationBufferLength); BufOffset = le32_to_cpu (buf->InformationBufferOffset); -#ifdef VERBOSE +#ifdef VERBOSE_DEBUG DBG("%s: Length: %d\n", __func__, BufLength); DBG("%s: Offset: %d\n", __func__, BufOffset); DBG("%s: InfoBuffer: ", __func__); @@ -919,10 +679,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + params->resp_avail(params->v); return 0; } @@ -930,6 +687,7 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) { rndis_reset_cmplt_type *resp; rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); if (!r) @@ -942,10 +700,7 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) /* resent information */ resp->AddressingReset = __constant_cpu_to_le32 (1); - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + params->resp_avail(params->v); return 0; } @@ -954,6 +709,7 @@ static int rndis_keepalive_response (int configNr, { rndis_keepalive_cmplt_type *resp; rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; /* host "should" check only in RNDIS_DATA_INITIALIZED state */ @@ -968,10 +724,7 @@ static int rndis_keepalive_response (int configNr, resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + params->resp_avail(params->v); return 0; } @@ -983,8 +736,9 @@ static int rndis_indicate_status_msg (int configNr, u32 status) { rndis_indicate_status_msg_type *resp; rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; - if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED) + if (params->state == RNDIS_UNINITIALIZED) return -ENOTSUPP; r = rndis_add_response (configNr, @@ -1000,9 +754,7 @@ static int rndis_indicate_status_msg (int configNr, u32 status) resp->StatusBufferLength = __constant_cpu_to_le32 (0); resp->StatusBufferOffset = __constant_cpu_to_le32 (0); - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + params->resp_avail(params->v); return 0; } @@ -1029,7 +781,6 @@ void rndis_uninit (int configNr) if (configNr >= RNDIS_MAX_CONFIGS) return; - rndis_per_dev_params [configNr].used = 0; rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED; /* drain the response queue */ @@ -1142,21 +893,25 @@ int rndis_msg_parser (u8 configNr, u8 *buf) return -ENOTSUPP; } -int rndis_register (int (* rndis_control_ack) (struct net_device *)) +int rndis_register(void (*resp_avail)(void *v), void *v) { u8 i; + if (!resp_avail) + return -EINVAL; + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { if (!rndis_per_dev_params [i].used) { rndis_per_dev_params [i].used = 1; - rndis_per_dev_params [i].ack = rndis_control_ack; + rndis_per_dev_params [i].resp_avail = resp_avail; + rndis_per_dev_params [i].v = v; DBG("%s: configNr = %d\n", __func__, i); return i; } } DBG("failed\n"); - return -1; + return -ENODEV; } void rndis_deregister (int configNr) @@ -1169,16 +924,14 @@ void rndis_deregister (int configNr) return; } -int rndis_set_param_dev (u8 configNr, struct net_device *dev, - struct net_device_stats *stats, - u16 *cdc_filter) +int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) { DBG("%s:\n", __func__ ); - if (!dev || !stats) return -1; + if (!dev) + return -EINVAL; if (configNr >= RNDIS_MAX_CONFIGS) return -1; rndis_per_dev_params [configNr].dev = dev; - rndis_per_dev_params [configNr].stats = stats; rndis_per_dev_params [configNr].filter = cdc_filter; return 0; @@ -1296,14 +1049,11 @@ int rndis_rm_hdr(struct sk_buff *skb) #ifdef CONFIG_USB_GADGET_DEBUG_FILES -static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, - void *data) +static int rndis_proc_show(struct seq_file *m, void *v) { - char *out = page; - int len; - rndis_params *param = (rndis_params *) data; + rndis_params *param = m->private; - out += snprintf (out, count, + seq_printf(m, "Config Nr. %d\n" "used : %s\n" "state : %s\n" @@ -1326,25 +1076,13 @@ static int rndis_proc_read (char *page, char **start, off_t off, int count, int (param->media_state) ? 0 : param->speed*100, (param->media_state) ? "disconnected" : "connected", param->vendorID, param->vendorDescr); - - len = out - page; - len -= off; - - if (len < count) { - *eof = 1; - if (len <= 0) - return 0; - } else - len = count; - - *start = page + off; - return len; + return 0; } -static int rndis_proc_write (struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t rndis_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { - rndis_params *p = data; + rndis_params *p = PDE(file->f_path.dentry->d_inode)->data; u32 speed = 0; int i, fl_speed = 0; @@ -1386,6 +1124,20 @@ static int rndis_proc_write (struct file *file, const char __user *buffer, return count; } +static int rndis_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, rndis_proc_show, PDE(inode)->data); +} + +static const struct file_operations rndis_proc_fops = { + .owner = THIS_MODULE, + .open = rndis_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = rndis_proc_write, +}; + #define NAME_TEMPLATE "driver/rndis-%03d" static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; @@ -1403,7 +1155,9 @@ int __init rndis_init (void) sprintf (name, NAME_TEMPLATE, i); if (!(rndis_connect_state [i] - = create_proc_entry (name, 0660, NULL))) + = proc_create_data(name, 0660, NULL, + &rndis_proc_fops, + (void *)(rndis_per_dev_params + i)))) { DBG("%s :remove entries", __func__); while (i) { @@ -1413,11 +1167,6 @@ int __init rndis_init (void) DBG("\n"); return -EIO; } - - rndis_connect_state [i]->write_proc = rndis_proc_write; - rndis_connect_state [i]->read_proc = rndis_proc_read; - rndis_connect_state [i]->data = (void *) - (rndis_per_dev_params + i); #endif rndis_per_dev_params [i].confignr = i; rndis_per_dev_params [i].used = 0; diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 397b149f3ca7..aac61dfe0f03 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h @@ -1,8 +1,6 @@ /* * RNDIS Definitions for Remote NDIS * - * Version: $Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $ - * * Authors: Benedikt Spranger, Pengutronix * Robert Schwebel, Pengutronix * @@ -235,20 +233,19 @@ typedef struct rndis_params const u8 *host_mac; u16 *filter; struct net_device *dev; - struct net_device_stats *stats; u32 vendorID; const char *vendorDescr; - int (*ack) (struct net_device *); + void (*resp_avail)(void *v); + void *v; struct list_head resp_queue; } rndis_params; /* RNDIS Message parser and other useless functions */ int rndis_msg_parser (u8 configNr, u8 *buf); -int rndis_register (int (*rndis_control_ack) (struct net_device *)); +int rndis_register(void (*resp_avail)(void *v), void *v); void rndis_deregister (int configNr); int rndis_set_param_dev (u8 configNr, struct net_device *dev, - struct net_device_stats *stats, u16 *cdc_filter); int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr); diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index fa019fa73334..b3699afff002 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -1,15 +1,9 @@ /* - * g_serial.c -- USB gadget serial driver + * serial.c -- USB gadget serial driver * - * Copyright 2003 (C) Al Borchers (alborchers@steinerpoint.com) - * - * This code is based in part on the Gadget Zero driver, which - * is Copyright (C) 2003 by David Brownell, all rights reserved. - * - * This code also borrows from usbserial.c, which is - * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2000 Peter Berger (pberger@brimson.com) - * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 by David Brownell + * Copyright (C) 2008 by Nokia Corporation * * This software is distributed under the terms of the GNU General * Public License ("GPL") as published by the Free Software Foundation, @@ -22,2254 +16,237 @@ #include <linux/tty.h> #include <linux/tty_flip.h> -#include <linux/usb/ch9.h> -#include <linux/usb/cdc.h> -#include <linux/usb/gadget.h> - +#include "u_serial.h" #include "gadget_chips.h" /* Defines */ -#define GS_VERSION_STR "v2.2" -#define GS_VERSION_NUM 0x2200 +#define GS_VERSION_STR "v2.4" +#define GS_VERSION_NUM 0x2400 #define GS_LONG_NAME "Gadget Serial" -#define GS_SHORT_NAME "g_serial" - -#define GS_MAJOR 127 -#define GS_MINOR_START 0 - -/* REVISIT only one port is supported for now; - * see gs_{send,recv}_packet() ... no multiplexing, - * and no support for multiple ACM devices. - */ -#define GS_NUM_PORTS 1 - -#define GS_NUM_CONFIGS 1 -#define GS_NO_CONFIG_ID 0 -#define GS_BULK_CONFIG_ID 1 -#define GS_ACM_CONFIG_ID 2 - -#define GS_MAX_NUM_INTERFACES 2 -#define GS_BULK_INTERFACE_ID 0 -#define GS_CONTROL_INTERFACE_ID 0 -#define GS_DATA_INTERFACE_ID 1 - -#define GS_MAX_DESC_LEN 256 - -#define GS_DEFAULT_READ_Q_SIZE 32 -#define GS_DEFAULT_WRITE_Q_SIZE 32 - -#define GS_DEFAULT_WRITE_BUF_SIZE 8192 -#define GS_TMP_BUF_SIZE 8192 - -#define GS_CLOSE_TIMEOUT 15 - -#define GS_DEFAULT_USE_ACM 0 - -/* 9600-8-N-1 ... matches init_termios.c_cflag and defaults - * expected by "usbser.sys" on MS-Windows. - */ -#define GS_DEFAULT_DTE_RATE 9600 -#define GS_DEFAULT_DATA_BITS 8 -#define GS_DEFAULT_PARITY USB_CDC_NO_PARITY -#define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS - -/* maxpacket and other transfer characteristics vary by speed. */ -static inline struct usb_endpoint_descriptor * -choose_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, - struct usb_endpoint_descriptor *fs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} - - -/* debug settings */ -#ifdef DEBUG -static int debug = 1; -#else -#define debug 0 -#endif - -#define gs_debug(format, arg...) \ - do { if (debug) pr_debug(format, ## arg); } while (0) -#define gs_debug_level(level, format, arg...) \ - do { if (debug >= level) pr_debug(format, ## arg); } while (0) +#define GS_VERSION_NAME GS_LONG_NAME " " GS_VERSION_STR +/*-------------------------------------------------------------------------*/ /* Thanks to NetChip Technologies for donating this product ID. - * - * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. - */ +* +* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! +* Instead: allocate your own, using normal USB-IF procedures. +*/ #define GS_VENDOR_ID 0x0525 /* NetChip */ #define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */ #define GS_CDC_PRODUCT_ID 0xa4a7 /* ... as CDC-ACM */ -#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ -#define GS_NOTIFY_MAXPACKET 8 +/* string IDs are assigned dynamically */ +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 +#define STRING_DESCRIPTION_IDX 2 -/* circular buffer */ -struct gs_buf { - unsigned int buf_size; - char *buf_buf; - char *buf_get; - char *buf_put; -}; +static char manufacturer[50]; -/* the port structure holds info for each port, one for each minor number */ -struct gs_port { - struct gs_dev *port_dev; /* pointer to device struct */ - struct tty_struct *port_tty; /* pointer to tty struct */ - spinlock_t port_lock; - int port_num; - int port_open_count; - int port_in_use; /* open/close in progress */ - wait_queue_head_t port_write_wait;/* waiting to write */ - struct gs_buf *port_write_buf; - struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ - u16 port_handshake_bits; -#define RS232_RTS (1 << 1) -#define RS232_DTE (1 << 0) +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer, + [STRING_PRODUCT_IDX].s = GS_VERSION_NAME, + [STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */, + { } /* end of list */ }; -/* the device structure holds info for the USB device */ -struct gs_dev { - struct usb_gadget *dev_gadget; /* gadget device pointer */ - spinlock_t dev_lock; /* lock for set/reset config */ - int dev_config; /* configuration number */ - struct usb_ep *dev_notify_ep; /* address of notify endpoint */ - struct usb_ep *dev_in_ep; /* address of in endpoint */ - struct usb_ep *dev_out_ep; /* address of out endpoint */ - struct usb_endpoint_descriptor /* descriptor of notify ep */ - *dev_notify_ep_desc; - struct usb_endpoint_descriptor /* descriptor of in endpoint */ - *dev_in_ep_desc; - struct usb_endpoint_descriptor /* descriptor of out endpoint */ - *dev_out_ep_desc; - struct usb_request *dev_ctrl_req; /* control request */ - struct list_head dev_req_list; /* list of write requests */ - int dev_sched_port; /* round robin port scheduled */ - struct gs_port *dev_port[GS_NUM_PORTS]; /* the ports */ +static struct usb_gadget_strings stringtab_dev = { + .language = 0x0409, /* en-us */ + .strings = strings_dev, }; - -/* Functions */ - -/* tty driver internals */ -static int gs_send(struct gs_dev *dev); -static int gs_send_packet(struct gs_dev *dev, char *packet, - unsigned int size); -static int gs_recv_packet(struct gs_dev *dev, char *packet, - unsigned int size); -static void gs_read_complete(struct usb_ep *ep, struct usb_request *req); -static void gs_write_complete(struct usb_ep *ep, struct usb_request *req); - -/* gadget driver internals */ -static int gs_set_config(struct gs_dev *dev, unsigned config); -static void gs_reset_config(struct gs_dev *dev); -static int gs_build_config_buf(u8 *buf, struct usb_gadget *g, - u8 type, unsigned int index, int is_otg); - -static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, - gfp_t kmalloc_flags); -static void gs_free_req(struct usb_ep *ep, struct usb_request *req); - -static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags); -static void gs_free_ports(struct gs_dev *dev); - -/* circular buffer */ -static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags); -static void gs_buf_free(struct gs_buf *gb); -static void gs_buf_clear(struct gs_buf *gb); -static unsigned int gs_buf_data_avail(struct gs_buf *gb); -static unsigned int gs_buf_space_avail(struct gs_buf *gb); -static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, - unsigned int count); -static unsigned int gs_buf_get(struct gs_buf *gb, char *buf, - unsigned int count); - - -/* Globals */ - -static struct gs_dev *gs_device; - -static struct mutex gs_open_close_lock[GS_NUM_PORTS]; - - -/*-------------------------------------------------------------------------*/ - -/* USB descriptors */ - -#define GS_MANUFACTURER_STR_ID 1 -#define GS_PRODUCT_STR_ID 2 -#define GS_SERIAL_STR_ID 3 -#define GS_BULK_CONFIG_STR_ID 4 -#define GS_ACM_CONFIG_STR_ID 5 -#define GS_CONTROL_STR_ID 6 -#define GS_DATA_STR_ID 7 - -/* static strings, in UTF-8 */ -static char manufacturer[50]; -static struct usb_string gs_strings[] = { - { GS_MANUFACTURER_STR_ID, manufacturer }, - { GS_PRODUCT_STR_ID, GS_LONG_NAME }, - { GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" }, - { GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" }, - { GS_CONTROL_STR_ID, "Gadget Serial Control" }, - { GS_DATA_STR_ID, "Gadget Serial Data" }, - { } /* end of list */ -}; - -static struct usb_gadget_strings gs_string_table = { - .language = 0x0409, /* en-us */ - .strings = gs_strings, +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, }; -static struct usb_device_descriptor gs_device_desc = { +static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = __constant_cpu_to_le16(0x0200), + /* .bDeviceClass = f(use_acm) */ .bDeviceSubClass = 0, .bDeviceProtocol = 0, + /* .bMaxPacketSize0 = f(hardware) */ .idVendor = __constant_cpu_to_le16(GS_VENDOR_ID), - .idProduct = __constant_cpu_to_le16(GS_PRODUCT_ID), - .iManufacturer = GS_MANUFACTURER_STR_ID, - .iProduct = GS_PRODUCT_STR_ID, - .bNumConfigurations = GS_NUM_CONFIGS, + /* .idProduct = f(use_acm) */ + /* .bcdDevice = f(hardware) */ + /* .iManufacturer = DYNAMIC */ + /* .iProduct = DYNAMIC */ + .bNumConfigurations = 1, }; -static struct usb_otg_descriptor gs_otg_descriptor = { - .bLength = sizeof(gs_otg_descriptor), +static struct usb_otg_descriptor otg_descriptor = { + .bLength = sizeof otg_descriptor, .bDescriptorType = USB_DT_OTG, - .bmAttributes = USB_OTG_SRP, -}; - -static struct usb_config_descriptor gs_bulk_config_desc = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - /* .wTotalLength computed dynamically */ - .bNumInterfaces = 1, - .bConfigurationValue = GS_BULK_CONFIG_ID, - .iConfiguration = GS_BULK_CONFIG_STR_ID, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, -}; - -static struct usb_config_descriptor gs_acm_config_desc = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - /* .wTotalLength computed dynamically */ - .bNumInterfaces = 2, - .bConfigurationValue = GS_ACM_CONFIG_ID, - .iConfiguration = GS_ACM_CONFIG_STR_ID, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, -}; - -static const struct usb_interface_descriptor gs_bulk_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = GS_BULK_INTERFACE_ID, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = GS_DATA_STR_ID, -}; - -static const struct usb_interface_descriptor gs_control_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = GS_CONTROL_INTERFACE_ID, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, - .iInterface = GS_CONTROL_STR_ID, -}; - -static const struct usb_interface_descriptor gs_data_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = GS_DATA_INTERFACE_ID, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = GS_DATA_STR_ID, -}; - -static const struct usb_cdc_header_desc gs_header_desc = { - .bLength = sizeof(gs_header_desc), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), -}; - -static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = { - .bLength = sizeof(gs_call_mgmt_descriptor), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, - .bmCapabilities = 0, - .bDataInterface = 1, /* index of data interface */ -}; - -static struct usb_cdc_acm_descriptor gs_acm_descriptor = { - .bLength = sizeof(gs_acm_descriptor), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ACM_TYPE, - .bmCapabilities = (1 << 1), -}; - -static const struct usb_cdc_union_desc gs_union_desc = { - .bLength = sizeof(gs_union_desc), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_UNION_TYPE, - .bMasterInterface0 = 0, /* index of control interface */ - .bSlaveInterface0 = 1, /* index of data interface */ -}; - -static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), - .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, -}; - -static struct usb_endpoint_descriptor gs_fullspeed_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_endpoint_descriptor gs_fullspeed_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static const struct usb_descriptor_header *gs_bulk_fullspeed_function[] = { - (struct usb_descriptor_header *) &gs_otg_descriptor, - (struct usb_descriptor_header *) &gs_bulk_interface_desc, - (struct usb_descriptor_header *) &gs_fullspeed_in_desc, - (struct usb_descriptor_header *) &gs_fullspeed_out_desc, - NULL, -}; - -static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = { - (struct usb_descriptor_header *) &gs_otg_descriptor, - (struct usb_descriptor_header *) &gs_control_interface_desc, - (struct usb_descriptor_header *) &gs_header_desc, - (struct usb_descriptor_header *) &gs_call_mgmt_descriptor, - (struct usb_descriptor_header *) &gs_acm_descriptor, - (struct usb_descriptor_header *) &gs_union_desc, - (struct usb_descriptor_header *) &gs_fullspeed_notify_desc, - (struct usb_descriptor_header *) &gs_data_interface_desc, - (struct usb_descriptor_header *) &gs_fullspeed_in_desc, - (struct usb_descriptor_header *) &gs_fullspeed_out_desc, - NULL, -}; -static struct usb_endpoint_descriptor gs_highspeed_notify_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), - .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, -}; - -static struct usb_endpoint_descriptor gs_highspeed_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor gs_highspeed_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_qualifier_descriptor gs_qualifier_desc = { - .bLength = sizeof(struct usb_qualifier_descriptor), - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16 (0x0200), - /* assumes ep0 uses the same value for both speeds ... */ - .bNumConfigurations = GS_NUM_CONFIGS, -}; - -static const struct usb_descriptor_header *gs_bulk_highspeed_function[] = { - (struct usb_descriptor_header *) &gs_otg_descriptor, - (struct usb_descriptor_header *) &gs_bulk_interface_desc, - (struct usb_descriptor_header *) &gs_highspeed_in_desc, - (struct usb_descriptor_header *) &gs_highspeed_out_desc, - NULL, + /* REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, }; -static const struct usb_descriptor_header *gs_acm_highspeed_function[] = { - (struct usb_descriptor_header *) &gs_otg_descriptor, - (struct usb_descriptor_header *) &gs_control_interface_desc, - (struct usb_descriptor_header *) &gs_header_desc, - (struct usb_descriptor_header *) &gs_call_mgmt_descriptor, - (struct usb_descriptor_header *) &gs_acm_descriptor, - (struct usb_descriptor_header *) &gs_union_desc, - (struct usb_descriptor_header *) &gs_highspeed_notify_desc, - (struct usb_descriptor_header *) &gs_data_interface_desc, - (struct usb_descriptor_header *) &gs_highspeed_in_desc, - (struct usb_descriptor_header *) &gs_highspeed_out_desc, +static const struct usb_descriptor_header *otg_desc[] = { + (struct usb_descriptor_header *) &otg_descriptor, NULL, }; - /*-------------------------------------------------------------------------*/ /* Module */ -MODULE_DESCRIPTION(GS_LONG_NAME); +MODULE_DESCRIPTION(GS_VERSION_NAME); MODULE_AUTHOR("Al Borchers"); +MODULE_AUTHOR("David Brownell"); MODULE_LICENSE("GPL"); -#ifdef DEBUG -module_param(debug, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); -#endif - -static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE; -module_param(read_q_size, uint, S_IRUGO); -MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32"); - -static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE; -module_param(write_q_size, uint, S_IRUGO); -MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32"); +static int use_acm = true; +module_param(use_acm, bool, 0); +MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes"); -static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE; -module_param(write_buf_size, uint, S_IRUGO); -MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192"); - -static unsigned int use_acm = GS_DEFAULT_USE_ACM; -module_param(use_acm, uint, S_IRUGO); -MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no"); +static unsigned n_ports = 1; +module_param(n_ports, uint, 0); +MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); /*-------------------------------------------------------------------------*/ -/* TTY Driver */ - -/* - * gs_open - */ -static int gs_open(struct tty_struct *tty, struct file *file) -{ - int port_num; - unsigned long flags; - struct gs_port *port; - struct gs_dev *dev; - struct gs_buf *buf; - struct mutex *mtx; - int ret; - - port_num = tty->index; - - gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file); - - if (port_num < 0 || port_num >= GS_NUM_PORTS) { - pr_err("gs_open: (%d,%p,%p) invalid port number\n", - port_num, tty, file); - return -ENODEV; - } - - dev = gs_device; - - if (dev == NULL) { - pr_err("gs_open: (%d,%p,%p) NULL device pointer\n", - port_num, tty, file); - return -ENODEV; - } - - mtx = &gs_open_close_lock[port_num]; - if (mutex_lock_interruptible(mtx)) { - pr_err("gs_open: (%d,%p,%p) interrupted waiting for mutex\n", - port_num, tty, file); - return -ERESTARTSYS; - } - - spin_lock_irqsave(&dev->dev_lock, flags); - - if (dev->dev_config == GS_NO_CONFIG_ID) { - pr_err("gs_open: (%d,%p,%p) device is not connected\n", - port_num, tty, file); - ret = -ENODEV; - goto exit_unlock_dev; - } - - port = dev->dev_port[port_num]; - - if (port == NULL) { - pr_err("gs_open: (%d,%p,%p) NULL port pointer\n", - port_num, tty, file); - ret = -ENODEV; - goto exit_unlock_dev; - } - - spin_lock(&port->port_lock); - spin_unlock(&dev->dev_lock); - - if (port->port_dev == NULL) { - pr_err("gs_open: (%d,%p,%p) port disconnected (1)\n", - port_num, tty, file); - ret = -EIO; - goto exit_unlock_port; - } - - if (port->port_open_count > 0) { - ++port->port_open_count; - gs_debug("gs_open: (%d,%p,%p) already open\n", - port_num, tty, file); - ret = 0; - goto exit_unlock_port; - } - - tty->driver_data = NULL; - - /* mark port as in use, we can drop port lock and sleep if necessary */ - port->port_in_use = 1; - - /* allocate write buffer on first open */ - if (port->port_write_buf == NULL) { - spin_unlock_irqrestore(&port->port_lock, flags); - buf = gs_buf_alloc(write_buf_size, GFP_KERNEL); - spin_lock_irqsave(&port->port_lock, flags); - - /* might have been disconnected while asleep, check */ - if (port->port_dev == NULL) { - pr_err("gs_open: (%d,%p,%p) port disconnected (2)\n", - port_num, tty, file); - port->port_in_use = 0; - ret = -EIO; - goto exit_unlock_port; - } - - if ((port->port_write_buf=buf) == NULL) { - pr_err("gs_open: (%d,%p,%p) cannot allocate " - "port write buffer\n", - port_num, tty, file); - port->port_in_use = 0; - ret = -ENOMEM; - goto exit_unlock_port; - } - - } - - /* wait for carrier detect (not implemented) */ - - /* might have been disconnected while asleep, check */ - if (port->port_dev == NULL) { - pr_err("gs_open: (%d,%p,%p) port disconnected (3)\n", - port_num, tty, file); - port->port_in_use = 0; - ret = -EIO; - goto exit_unlock_port; - } - - tty->driver_data = port; - port->port_tty = tty; - port->port_open_count = 1; - port->port_in_use = 0; - - gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file); - - ret = 0; - -exit_unlock_port: - spin_unlock_irqrestore(&port->port_lock, flags); - mutex_unlock(mtx); - return ret; - -exit_unlock_dev: - spin_unlock_irqrestore(&dev->dev_lock, flags); - mutex_unlock(mtx); - return ret; - -} - -/* - * gs_close - */ - -static int gs_write_finished_event_safely(struct gs_port *p) -{ - int cond; - - spin_lock_irq(&(p)->port_lock); - cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); - spin_unlock_irq(&(p)->port_lock); - return cond; -} - -static void gs_close(struct tty_struct *tty, struct file *file) -{ - struct gs_port *port = tty->driver_data; - struct mutex *mtx; - - if (port == NULL) { - pr_err("gs_close: NULL port pointer\n"); - return; - } - - gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file); - - mtx = &gs_open_close_lock[port->port_num]; - mutex_lock(mtx); - - spin_lock_irq(&port->port_lock); - - if (port->port_open_count == 0) { - pr_err("gs_close: (%d,%p,%p) port is already closed\n", - port->port_num, tty, file); - goto exit; - } - - if (port->port_open_count > 1) { - --port->port_open_count; - goto exit; - } - - /* free disconnected port on final close */ - if (port->port_dev == NULL) { - kfree(port); - goto exit; - } - - /* mark port as closed but in use, we can drop port lock */ - /* and sleep if necessary */ - port->port_in_use = 1; - port->port_open_count = 0; - - /* wait for write buffer to drain, or */ - /* at most GS_CLOSE_TIMEOUT seconds */ - if (gs_buf_data_avail(port->port_write_buf) > 0) { - spin_unlock_irq(&port->port_lock); - wait_event_interruptible_timeout(port->port_write_wait, - gs_write_finished_event_safely(port), - GS_CLOSE_TIMEOUT * HZ); - spin_lock_irq(&port->port_lock); - } - - /* free disconnected port on final close */ - /* (might have happened during the above sleep) */ - if (port->port_dev == NULL) { - kfree(port); - goto exit; - } - - gs_buf_clear(port->port_write_buf); - - tty->driver_data = NULL; - port->port_tty = NULL; - port->port_in_use = 0; - - gs_debug("gs_close: (%d,%p,%p) completed\n", - port->port_num, tty, file); - -exit: - spin_unlock_irq(&port->port_lock); - mutex_unlock(mtx); -} - -/* - * gs_write - */ -static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count) +static int __init serial_bind_config(struct usb_configuration *c) { - unsigned long flags; - struct gs_port *port = tty->driver_data; - int ret; - - if (port == NULL) { - pr_err("gs_write: NULL port pointer\n"); - return -EIO; - } - - gs_debug("gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty, - count); - - if (count == 0) - return 0; - - spin_lock_irqsave(&port->port_lock, flags); - - if (port->port_dev == NULL) { - pr_err("gs_write: (%d,%p) port is not connected\n", - port->port_num, tty); - ret = -EIO; - goto exit; - } - - if (port->port_open_count == 0) { - pr_err("gs_write: (%d,%p) port is closed\n", - port->port_num, tty); - ret = -EBADF; - goto exit; - } - - count = gs_buf_put(port->port_write_buf, buf, count); - - spin_unlock_irqrestore(&port->port_lock, flags); - - gs_send(gs_device); - - gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty, - count); + unsigned i; + int status = 0; - return count; - -exit: - spin_unlock_irqrestore(&port->port_lock, flags); - return ret; -} - -/* - * gs_put_char - */ -static int gs_put_char(struct tty_struct *tty, unsigned char ch) -{ - unsigned long flags; - struct gs_port *port = tty->driver_data; - int ret = 0; - - if (port == NULL) { - pr_err("gs_put_char: NULL port pointer\n"); - return 0; - } - - gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n", - port->port_num, tty, ch, __builtin_return_address(0)); - - spin_lock_irqsave(&port->port_lock, flags); - - if (port->port_dev == NULL) { - pr_err("gs_put_char: (%d,%p) port is not connected\n", - port->port_num, tty); - goto exit; - } - - if (port->port_open_count == 0) { - pr_err("gs_put_char: (%d,%p) port is closed\n", - port->port_num, tty); - goto exit; - } - - ret = gs_buf_put(port->port_write_buf, &ch, 1); - -exit: - spin_unlock_irqrestore(&port->port_lock, flags); - return ret; -} - -/* - * gs_flush_chars - */ -static void gs_flush_chars(struct tty_struct *tty) -{ - unsigned long flags; - struct gs_port *port = tty->driver_data; - - if (port == NULL) { - pr_err("gs_flush_chars: NULL port pointer\n"); - return; - } - - gs_debug("gs_flush_chars: (%d,%p)\n", port->port_num, tty); - - spin_lock_irqsave(&port->port_lock, flags); - - if (port->port_dev == NULL) { - pr_err("gs_flush_chars: (%d,%p) port is not connected\n", - port->port_num, tty); - goto exit; - } - - if (port->port_open_count == 0) { - pr_err("gs_flush_chars: (%d,%p) port is closed\n", - port->port_num, tty); - goto exit; - } - - spin_unlock_irqrestore(&port->port_lock, flags); - - gs_send(gs_device); - - return; - -exit: - spin_unlock_irqrestore(&port->port_lock, flags); -} - -/* - * gs_write_room - */ -static int gs_write_room(struct tty_struct *tty) -{ - - int room = 0; - unsigned long flags; - struct gs_port *port = tty->driver_data; - - - if (port == NULL) - return 0; - - spin_lock_irqsave(&port->port_lock, flags); - - if (port->port_dev != NULL && port->port_open_count > 0 - && port->port_write_buf != NULL) - room = gs_buf_space_avail(port->port_write_buf); - - spin_unlock_irqrestore(&port->port_lock, flags); - - gs_debug("gs_write_room: (%d,%p) room=%d\n", - port->port_num, tty, room); - - return room; -} - -/* - * gs_chars_in_buffer - */ -static int gs_chars_in_buffer(struct tty_struct *tty) -{ - int chars = 0; - unsigned long flags; - struct gs_port *port = tty->driver_data; - - if (port == NULL) - return 0; - - spin_lock_irqsave(&port->port_lock, flags); - - if (port->port_dev != NULL && port->port_open_count > 0 - && port->port_write_buf != NULL) - chars = gs_buf_data_avail(port->port_write_buf); - - spin_unlock_irqrestore(&port->port_lock, flags); - - gs_debug("gs_chars_in_buffer: (%d,%p) chars=%d\n", - port->port_num, tty, chars); - - return chars; -} - -/* - * gs_throttle - */ -static void gs_throttle(struct tty_struct *tty) -{ -} - -/* - * gs_unthrottle - */ -static void gs_unthrottle(struct tty_struct *tty) -{ -} - -/* - * gs_break - */ -static void gs_break(struct tty_struct *tty, int break_state) -{ -} - -/* - * gs_ioctl - */ -static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct gs_port *port = tty->driver_data; - - if (port == NULL) { - pr_err("gs_ioctl: NULL port pointer\n"); - return -EIO; + for (i = 0; i < n_ports && status == 0; i++) { + if (use_acm) + status = acm_bind_config(c, i); + else + status = gser_bind_config(c, i); } - - gs_debug("gs_ioctl: (%d,%p,%p) cmd=0x%4.4x, arg=%lu\n", - port->port_num, tty, file, cmd, arg); - - /* handle ioctls */ - - /* could not handle ioctl */ - return -ENOIOCTLCMD; -} - -/* - * gs_set_termios - */ -static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) -{ + return status; } -static const struct tty_operations gs_tty_ops = { - .open = gs_open, - .close = gs_close, - .write = gs_write, - .put_char = gs_put_char, - .flush_chars = gs_flush_chars, - .write_room = gs_write_room, - .ioctl = gs_ioctl, - .set_termios = gs_set_termios, - .throttle = gs_throttle, - .unthrottle = gs_unthrottle, - .break_ctl = gs_break, - .chars_in_buffer = gs_chars_in_buffer, +static struct usb_configuration serial_config_driver = { + /* .label = f(use_acm) */ + .bind = serial_bind_config, + /* .bConfigurationValue = f(use_acm) */ + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* 2 mA, minimal */ }; -/*-------------------------------------------------------------------------*/ - -/* -* gs_send -* -* This function finds available write requests, calls -* gs_send_packet to fill these packets with data, and -* continues until either there are no more write requests -* available or no more data to send. This function is -* run whenever data arrives or write requests are available. -*/ -static int gs_send(struct gs_dev *dev) -{ - int ret,len; - unsigned long flags; - struct usb_ep *ep; - struct usb_request *req; - - if (dev == NULL) { - pr_err("gs_send: NULL device pointer\n"); - return -ENODEV; - } - - spin_lock_irqsave(&dev->dev_lock, flags); - - ep = dev->dev_in_ep; - - while(!list_empty(&dev->dev_req_list)) { - - req = list_entry(dev->dev_req_list.next, - struct usb_request, list); - - len = gs_send_packet(dev, req->buf, ep->maxpacket); - - if (len > 0) { - gs_debug_level(3, "gs_send: len=%d, 0x%2.2x " - "0x%2.2x 0x%2.2x ...\n", len, - *((unsigned char *)req->buf), - *((unsigned char *)req->buf+1), - *((unsigned char *)req->buf+2)); - list_del(&req->list); - req->length = len; - spin_unlock_irqrestore(&dev->dev_lock, flags); - if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { - pr_err( - "gs_send: cannot queue read request, ret=%d\n", - ret); - spin_lock_irqsave(&dev->dev_lock, flags); - break; - } - spin_lock_irqsave(&dev->dev_lock, flags); - } else { - break; - } - - } - - spin_unlock_irqrestore(&dev->dev_lock, flags); - - return 0; -} - -/* - * gs_send_packet - * - * If there is data to send, a packet is built in the given - * buffer and the size is returned. If there is no data to - * send, 0 is returned. If there is any error a negative - * error number is returned. - * - * Called during USB completion routine, on interrupt time. - * - * We assume that disconnect will not happen until all completion - * routines have completed, so we can assume that the dev_port - * array does not change during the lifetime of this function. - */ -static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size) -{ - unsigned int len; - struct gs_port *port; - - /* TEMPORARY -- only port 0 is supported right now */ - port = dev->dev_port[0]; - - if (port == NULL) { - pr_err("gs_send_packet: port=%d, NULL port pointer\n", 0); - return -EIO; - } - - spin_lock(&port->port_lock); - - len = gs_buf_data_avail(port->port_write_buf); - if (len < size) - size = len; - - if (size == 0) - goto exit; - - size = gs_buf_get(port->port_write_buf, packet, size); - - if (port->port_tty) - wake_up_interruptible(&port->port_tty->write_wait); - -exit: - spin_unlock(&port->port_lock); - return size; -} - -/* - * gs_recv_packet - * - * Called for each USB packet received. Reads the packet - * header and stuffs the data in the appropriate tty buffer. - * Returns 0 if successful, or a negative error number. - * - * Called during USB completion routine, on interrupt time. - * - * We assume that disconnect will not happen until all completion - * routines have completed, so we can assume that the dev_port - * array does not change during the lifetime of this function. - */ -static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size) -{ - unsigned int len; - struct gs_port *port; - int ret; - struct tty_struct *tty; - - /* TEMPORARY -- only port 0 is supported right now */ - port = dev->dev_port[0]; - - if (port == NULL) { - pr_err("gs_recv_packet: port=%d, NULL port pointer\n", - port->port_num); - return -EIO; - } - - spin_lock(&port->port_lock); - - if (port->port_open_count == 0) { - pr_err("gs_recv_packet: port=%d, port is closed\n", - port->port_num); - ret = -EIO; - goto exit; - } - - - tty = port->port_tty; - - if (tty == NULL) { - pr_err("gs_recv_packet: port=%d, NULL tty pointer\n", - port->port_num); - ret = -EIO; - goto exit; - } - - if (port->port_tty->magic != TTY_MAGIC) { - pr_err("gs_recv_packet: port=%d, bad tty magic\n", - port->port_num); - ret = -EIO; - goto exit; - } - - len = tty_buffer_request_room(tty, size); - if (len > 0) { - tty_insert_flip_string(tty, packet, len); - tty_flip_buffer_push(port->port_tty); - wake_up_interruptible(&port->port_tty->read_wait); - } - ret = 0; -exit: - spin_unlock(&port->port_lock); - return ret; -} - -/* -* gs_read_complete -*/ -static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) +static int __init gs_bind(struct usb_composite_dev *cdev) { - int ret; - struct gs_dev *dev = ep->driver_data; - - if (dev == NULL) { - pr_err("gs_read_complete: NULL device pointer\n"); - return; - } + int gcnum; + struct usb_gadget *gadget = cdev->gadget; + int status; - switch(req->status) { - case 0: - /* normal completion */ - gs_recv_packet(dev, req->buf, req->actual); -requeue: - req->length = ep->maxpacket; - if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { - pr_err( - "gs_read_complete: cannot queue read request, ret=%d\n", - ret); - } - break; - - case -ESHUTDOWN: - /* disconnect */ - gs_debug("gs_read_complete: shutdown\n"); - gs_free_req(ep, req); - break; - - default: - /* unexpected */ - pr_err( - "gs_read_complete: unexpected status error, status=%d\n", - req->status); - goto requeue; - break; - } -} - -/* -* gs_write_complete -*/ -static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct gs_dev *dev = ep->driver_data; - - if (dev == NULL) { - pr_err("gs_write_complete: NULL device pointer\n"); - return; - } + status = gserial_setup(cdev->gadget, n_ports); + if (status < 0) + return status; - switch(req->status) { - case 0: - /* normal completion */ -requeue: - spin_lock(&dev->dev_lock); - list_add(&req->list, &dev->dev_req_list); - spin_unlock(&dev->dev_lock); - - gs_send(dev); - - break; - - case -ESHUTDOWN: - /* disconnect */ - gs_debug("gs_write_complete: shutdown\n"); - gs_free_req(ep, req); - break; - - default: - pr_err( - "gs_write_complete: unexpected status error, status=%d\n", - req->status); - goto requeue; - break; - } -} + /* Allocate string descriptor numbers ... note that string + * contents can be overridden by the composite_dev glue. + */ -/*-------------------------------------------------------------------------*/ + /* device description: manufacturer, product */ + snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", + init_utsname()->sysname, init_utsname()->release, + gadget->name); + status = usb_string_id(cdev); + if (status < 0) + goto fail; + strings_dev[STRING_MANUFACTURER_IDX].id = status; -/* Gadget Driver */ + device_desc.iManufacturer = status; -/* - * gs_unbind - * - * Called on module unload. Frees the control request and device - * structure. - */ -static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget) -{ - struct gs_dev *dev = get_gadget_data(gadget); + status = usb_string_id(cdev); + if (status < 0) + goto fail; + strings_dev[STRING_PRODUCT_IDX].id = status; - gs_device = NULL; + device_desc.iProduct = status; - /* read/write requests already freed, only control request remains */ - if (dev != NULL) { - if (dev->dev_ctrl_req != NULL) { - gs_free_req(gadget->ep0, dev->dev_ctrl_req); - dev->dev_ctrl_req = NULL; - } - gs_reset_config(dev); - gs_free_ports(dev); - kfree(dev); - set_gadget_data(gadget, NULL); - } + /* config description */ + status = usb_string_id(cdev); + if (status < 0) + goto fail; + strings_dev[STRING_DESCRIPTION_IDX].id = status; - pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME, - GS_VERSION_STR); -} - -/* - * gs_bind - * - * Called on module load. Allocates and initializes the device - * structure and a control request. - */ -static int __init gs_bind(struct usb_gadget *gadget) -{ - int ret; - struct usb_ep *ep; - struct gs_dev *dev; - int gcnum; - - /* Some controllers can't support CDC ACM: - * - sh doesn't support multiple interfaces or configs; - * - sa1100 doesn't have a third interrupt endpoint - */ - if (gadget_is_sh(gadget) || gadget_is_sa1100(gadget)) - use_acm = 0; + serial_config_driver.iConfiguration = status; + /* set up other descriptors */ gcnum = usb_gadget_controller_number(gadget); if (gcnum >= 0) - gs_device_desc.bcdDevice = - cpu_to_le16(GS_VERSION_NUM | gcnum); + device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum); else { + /* this is so simple (for now, no altsettings) that it + * SHOULD NOT have problems with bulk-capable hardware. + * so warn about unrcognized controllers -- don't panic. + * + * things like configuration and altsetting numbering + * can need hardware-specific attention though. + */ pr_warning("gs_bind: controller '%s' not recognized\n", gadget->name); - /* unrecognized, but safe unless bulk is REALLY quirky */ - gs_device_desc.bcdDevice = - __constant_cpu_to_le16(GS_VERSION_NUM|0x0099); - } - - dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL); - if (dev == NULL) - return -ENOMEM; - - usb_ep_autoconfig_reset(gadget); - - ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc); - if (!ep) - goto autoconf_fail; - dev->dev_in_ep = ep; - ep->driver_data = dev; /* claim the endpoint */ - - ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc); - if (!ep) - goto autoconf_fail; - dev->dev_out_ep = ep; - ep->driver_data = dev; /* claim the endpoint */ - - if (use_acm) { - ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc); - if (!ep) { - pr_err("gs_bind: cannot run ACM on %s\n", gadget->name); - goto autoconf_fail; - } - gs_device_desc.idProduct = __constant_cpu_to_le16( - GS_CDC_PRODUCT_ID), - dev->dev_notify_ep = ep; - ep->driver_data = dev; /* claim the endpoint */ - } - - gs_device_desc.bDeviceClass = use_acm - ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; - gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; - - if (gadget_is_dualspeed(gadget)) { - gs_qualifier_desc.bDeviceClass = use_acm - ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; - /* assume ep0 uses the same packet size for both speeds */ - gs_qualifier_desc.bMaxPacketSize0 = - gs_device_desc.bMaxPacketSize0; - /* assume endpoints are dual-speed */ - gs_highspeed_notify_desc.bEndpointAddress = - gs_fullspeed_notify_desc.bEndpointAddress; - gs_highspeed_in_desc.bEndpointAddress = - gs_fullspeed_in_desc.bEndpointAddress; - gs_highspeed_out_desc.bEndpointAddress = - gs_fullspeed_out_desc.bEndpointAddress; - } - - usb_gadget_set_selfpowered(gadget); - - if (gadget_is_otg(gadget)) { - gs_otg_descriptor.bmAttributes |= USB_OTG_HNP, - gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM | 0x0099); } - gs_device = dev; - - snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - - dev->dev_gadget = gadget; - spin_lock_init(&dev->dev_lock); - INIT_LIST_HEAD(&dev->dev_req_list); - set_gadget_data(gadget, dev); - - if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) { - pr_err("gs_bind: cannot allocate ports\n"); - gs_unbind(gadget); - return ret; + if (gadget_is_otg(cdev->gadget)) { + serial_config_driver.descriptors = otg_desc; + serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - /* preallocate control response and buffer */ - dev->dev_ctrl_req = gs_alloc_req(gadget->ep0, GS_MAX_DESC_LEN, - GFP_KERNEL); - if (dev->dev_ctrl_req == NULL) { - gs_unbind(gadget); - return -ENOMEM; - } - gadget->ep0->driver_data = dev; + /* register our configuration */ + status = usb_add_config(cdev, &serial_config_driver); + if (status < 0) + goto fail; - pr_info("gs_bind: %s %s bound\n", - GS_LONG_NAME, GS_VERSION_STR); + INFO(cdev, "%s\n", GS_VERSION_NAME); return 0; -autoconf_fail: - kfree(dev); - pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name); - return -ENODEV; -} - -static int gs_setup_standard(struct usb_gadget *gadget, - const struct usb_ctrlrequest *ctrl) -{ - int ret = -EOPNOTSUPP; - struct gs_dev *dev = get_gadget_data(gadget); - struct usb_request *req = dev->dev_ctrl_req; - u16 wIndex = le16_to_cpu(ctrl->wIndex); - u16 wValue = le16_to_cpu(ctrl->wValue); - u16 wLength = le16_to_cpu(ctrl->wLength); - - switch (ctrl->bRequest) { - case USB_REQ_GET_DESCRIPTOR: - if (ctrl->bRequestType != USB_DIR_IN) - break; - - switch (wValue >> 8) { - case USB_DT_DEVICE: - ret = min(wLength, - (u16)sizeof(struct usb_device_descriptor)); - memcpy(req->buf, &gs_device_desc, ret); - break; - - case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) - break; - ret = min(wLength, - (u16)sizeof(struct usb_qualifier_descriptor)); - memcpy(req->buf, &gs_qualifier_desc, ret); - break; - - case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) - break; - /* fall through */ - case USB_DT_CONFIG: - ret = gs_build_config_buf(req->buf, gadget, - wValue >> 8, wValue & 0xff, - gadget_is_otg(gadget)); - if (ret >= 0) - ret = min(wLength, (u16)ret); - break; - - case USB_DT_STRING: - /* wIndex == language code. */ - ret = usb_gadget_get_string(&gs_string_table, - wValue & 0xff, req->buf); - if (ret >= 0) - ret = min(wLength, (u16)ret); - break; - } - break; - - case USB_REQ_SET_CONFIGURATION: - if (ctrl->bRequestType != 0) - break; - spin_lock(&dev->dev_lock); - ret = gs_set_config(dev, wValue); - spin_unlock(&dev->dev_lock); - break; - - case USB_REQ_GET_CONFIGURATION: - if (ctrl->bRequestType != USB_DIR_IN) - break; - *(u8 *)req->buf = dev->dev_config; - ret = min(wLength, (u16)1); - break; - - case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE - || !dev->dev_config - || wIndex >= GS_MAX_NUM_INTERFACES) - break; - if (dev->dev_config == GS_BULK_CONFIG_ID - && wIndex != GS_BULK_INTERFACE_ID) - break; - /* no alternate interface settings */ - if (wValue != 0) - break; - spin_lock(&dev->dev_lock); - /* PXA hardware partially handles SET_INTERFACE; - * we need to kluge around that interference. */ - if (gadget_is_pxa(gadget)) { - ret = gs_set_config(dev, use_acm ? - GS_ACM_CONFIG_ID : GS_BULK_CONFIG_ID); - goto set_interface_done; - } - if (dev->dev_config != GS_BULK_CONFIG_ID - && wIndex == GS_CONTROL_INTERFACE_ID) { - if (dev->dev_notify_ep) { - usb_ep_disable(dev->dev_notify_ep); - usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc); - } - } else { - usb_ep_disable(dev->dev_in_ep); - usb_ep_disable(dev->dev_out_ep); - usb_ep_enable(dev->dev_in_ep, dev->dev_in_ep_desc); - usb_ep_enable(dev->dev_out_ep, dev->dev_out_ep_desc); - } - ret = 0; -set_interface_done: - spin_unlock(&dev->dev_lock); - break; - - case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE) - || dev->dev_config == GS_NO_CONFIG_ID) - break; - if (wIndex >= GS_MAX_NUM_INTERFACES - || (dev->dev_config == GS_BULK_CONFIG_ID - && wIndex != GS_BULK_INTERFACE_ID)) { - ret = -EDOM; - break; - } - /* no alternate interface settings */ - *(u8 *)req->buf = 0; - ret = min(wLength, (u16)1); - break; - - default: - pr_err("gs_setup: unknown standard request, type=%02x, " - "request=%02x, value=%04x, index=%04x, length=%d\n", - ctrl->bRequestType, ctrl->bRequest, - wValue, wIndex, wLength); - break; - } - - return ret; +fail: + gserial_cleanup(); + return status; } -static void gs_setup_complete_set_line_coding(struct usb_ep *ep, - struct usb_request *req) -{ - struct gs_dev *dev = ep->driver_data; - struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ - - switch (req->status) { - case 0: - /* normal completion */ - if (req->actual != sizeof(port->port_line_coding)) - usb_ep_set_halt(ep); - else if (port) { - struct usb_cdc_line_coding *value = req->buf; - - /* REVISIT: we currently just remember this data. - * If we change that, (a) validate it first, then - * (b) update whatever hardware needs updating. - */ - spin_lock(&port->port_lock); - port->port_line_coding = *value; - spin_unlock(&port->port_lock); - } - break; - - case -ESHUTDOWN: - /* disconnect */ - gs_free_req(ep, req); - break; - - default: - /* unexpected */ - break; - } - return; -} - -static int gs_setup_class(struct usb_gadget *gadget, - const struct usb_ctrlrequest *ctrl) -{ - int ret = -EOPNOTSUPP; - struct gs_dev *dev = get_gadget_data(gadget); - struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ - struct usb_request *req = dev->dev_ctrl_req; - u16 wIndex = le16_to_cpu(ctrl->wIndex); - u16 wValue = le16_to_cpu(ctrl->wValue); - u16 wLength = le16_to_cpu(ctrl->wLength); - - switch (ctrl->bRequest) { - case USB_CDC_REQ_SET_LINE_CODING: - if (wLength != sizeof(struct usb_cdc_line_coding)) - break; - ret = wLength; - req->complete = gs_setup_complete_set_line_coding; - break; - - case USB_CDC_REQ_GET_LINE_CODING: - ret = min_t(int, wLength, sizeof(struct usb_cdc_line_coding)); - if (port) { - spin_lock(&port->port_lock); - memcpy(req->buf, &port->port_line_coding, ret); - spin_unlock(&port->port_lock); - } - break; - - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - if (wLength != 0) - break; - ret = 0; - if (port) { - /* REVISIT: we currently just remember this data. - * If we change that, update whatever hardware needs - * updating. - */ - spin_lock(&port->port_lock); - port->port_handshake_bits = wValue; - spin_unlock(&port->port_lock); - } - break; - - default: - /* NOTE: strictly speaking, we should accept AT-commands - * using SEND_ENCPSULATED_COMMAND/GET_ENCAPSULATED_RESPONSE. - * But our call management descriptor says we don't handle - * call management, so we should be able to get by without - * handling those "required" commands (except by stalling). - */ - pr_err("gs_setup: unknown class request, " - "type=%02x, request=%02x, value=%04x, " - "index=%04x, length=%d\n", - ctrl->bRequestType, ctrl->bRequest, - wValue, wIndex, wLength); - break; - } - - return ret; -} - -/* - * gs_setup_complete - */ -static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) { - pr_err("gs_setup_complete: status error, status=%d, " - "actual=%d, length=%d\n", - req->status, req->actual, req->length); - } -} - -/* - * gs_setup - * - * Implements all the control endpoint functionality that's not - * handled in hardware or the hardware driver. - * - * Returns the size of the data sent to the host, or a negative - * error number. - */ -static int gs_setup(struct usb_gadget *gadget, - const struct usb_ctrlrequest *ctrl) -{ - int ret = -EOPNOTSUPP; - struct gs_dev *dev = get_gadget_data(gadget); - struct usb_request *req = dev->dev_ctrl_req; - u16 wIndex = le16_to_cpu(ctrl->wIndex); - u16 wValue = le16_to_cpu(ctrl->wValue); - u16 wLength = le16_to_cpu(ctrl->wLength); - - req->complete = gs_setup_complete; - - switch (ctrl->bRequestType & USB_TYPE_MASK) { - case USB_TYPE_STANDARD: - ret = gs_setup_standard(gadget, ctrl); - break; - - case USB_TYPE_CLASS: - ret = gs_setup_class(gadget, ctrl); - break; - - default: - pr_err("gs_setup: unknown request, type=%02x, request=%02x, " - "value=%04x, index=%04x, length=%d\n", - ctrl->bRequestType, ctrl->bRequest, - wValue, wIndex, wLength); - break; - } - - /* respond with data transfer before status phase? */ - if (ret >= 0) { - req->length = ret; - req->zero = ret < wLength - && (ret % gadget->ep0->maxpacket) == 0; - ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - if (ret < 0) { - pr_err("gs_setup: cannot queue response, ret=%d\n", - ret); - req->status = 0; - gs_setup_complete(gadget->ep0, req); - } - } - - /* device either stalls (ret < 0) or reports success */ - return ret; -} - -/* - * gs_disconnect - * - * Called when the device is disconnected. Frees the closed - * ports and disconnects open ports. Open ports will be freed - * on close. Then reallocates the ports for the next connection. - */ -static void gs_disconnect(struct usb_gadget *gadget) -{ - unsigned long flags; - struct gs_dev *dev = get_gadget_data(gadget); - - spin_lock_irqsave(&dev->dev_lock, flags); - - gs_reset_config(dev); - - /* free closed ports and disconnect open ports */ - /* (open ports will be freed when closed) */ - gs_free_ports(dev); - - /* re-allocate ports for the next connection */ - if (gs_alloc_ports(dev, GFP_ATOMIC) != 0) - pr_err("gs_disconnect: cannot re-allocate ports\n"); - - spin_unlock_irqrestore(&dev->dev_lock, flags); - - pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME); -} - -static struct usb_gadget_driver gs_gadget_driver = { -#ifdef CONFIG_USB_GADGET_DUALSPEED - .speed = USB_SPEED_HIGH, -#else - .speed = USB_SPEED_FULL, -#endif /* CONFIG_USB_GADGET_DUALSPEED */ - .function = GS_LONG_NAME, - .bind = gs_bind, - .unbind = gs_unbind, - .setup = gs_setup, - .disconnect = gs_disconnect, - .driver = { - .name = GS_SHORT_NAME, - .owner = THIS_MODULE, - }, +static struct usb_composite_driver gserial_driver = { + .name = "g_serial", + .dev = &device_desc, + .strings = dev_strings, + .bind = gs_bind, }; -/* - * gs_set_config - * - * Configures the device by enabling device specific - * optimizations, setting up the endpoints, allocating - * read and write requests and queuing read requests. - * - * The device lock must be held when calling this function. - */ -static int gs_set_config(struct gs_dev *dev, unsigned config) +static int __init init(void) { - int i; - int ret = 0; - struct usb_gadget *gadget = dev->dev_gadget; - struct usb_ep *ep; - struct usb_endpoint_descriptor *out, *in, *notify; - struct usb_request *req; - - if (dev == NULL) { - pr_err("gs_set_config: NULL device pointer\n"); - return 0; - } - - if (config == dev->dev_config) - return 0; - - gs_reset_config(dev); - - switch (config) { - case GS_NO_CONFIG_ID: - return 0; - case GS_BULK_CONFIG_ID: - if (use_acm) - return -EINVAL; - break; - case GS_ACM_CONFIG_ID: - if (!use_acm) - return -EINVAL; - break; - default: - return -EINVAL; - } - - in = choose_ep_desc(gadget, - &gs_highspeed_in_desc, - &gs_fullspeed_in_desc); - out = choose_ep_desc(gadget, - &gs_highspeed_out_desc, - &gs_fullspeed_out_desc); - notify = dev->dev_notify_ep - ? choose_ep_desc(gadget, - &gs_highspeed_notify_desc, - &gs_fullspeed_notify_desc) - : NULL; - - ret = usb_ep_enable(dev->dev_in_ep, in); - if (ret == 0) { - dev->dev_in_ep_desc = in; - } else { - pr_debug("%s: cannot enable %s %s, ret=%d\n", - __func__, "IN", dev->dev_in_ep->name, ret); - return ret; - } - - ret = usb_ep_enable(dev->dev_out_ep, out); - if (ret == 0) { - dev->dev_out_ep_desc = out; - } else { - pr_debug("%s: cannot enable %s %s, ret=%d\n", - __func__, "OUT", dev->dev_out_ep->name, ret); -fail0: - usb_ep_disable(dev->dev_in_ep); - return ret; - } - - if (notify) { - ret = usb_ep_enable(dev->dev_notify_ep, notify); - if (ret == 0) { - dev->dev_notify_ep_desc = notify; - } else { - pr_debug("%s: cannot enable %s %s, ret=%d\n", - __func__, "NOTIFY", - dev->dev_notify_ep->name, ret); - usb_ep_disable(dev->dev_out_ep); - goto fail0; - } - } - - dev->dev_config = config; - - /* allocate and queue read requests */ - ep = dev->dev_out_ep; - for (i=0; i<read_q_size && ret == 0; i++) { - if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) { - req->complete = gs_read_complete; - if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { - pr_err("gs_set_config: cannot queue read " - "request, ret=%d\n", ret); - } - } else { - pr_err("gs_set_config: cannot allocate " - "read requests\n"); - ret = -ENOMEM; - goto exit_reset_config; - } - } - - /* allocate write requests, and put on free list */ - ep = dev->dev_in_ep; - for (i=0; i<write_q_size; i++) { - req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC); - if (req) { - req->complete = gs_write_complete; - list_add(&req->list, &dev->dev_req_list); - } else { - pr_err("gs_set_config: cannot allocate " - "write requests\n"); - ret = -ENOMEM; - goto exit_reset_config; - } - } - - /* REVISIT the ACM mode should be able to actually *issue* some - * notifications, for at least serial state change events if - * not also for network connection; say so in bmCapabilities. + /* We *could* export two configs; that'd be much cleaner... + * but neither of these product IDs was defined that way. */ - - pr_info("gs_set_config: %s configured, %s speed %s config\n", - GS_LONG_NAME, - gadget->speed == USB_SPEED_HIGH ? "high" : "full", - config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM"); - - return 0; - -exit_reset_config: - gs_reset_config(dev); - return ret; -} - -/* - * gs_reset_config - * - * Mark the device as not configured, disable all endpoints, - * which forces completion of pending I/O and frees queued - * requests, and free the remaining write requests on the - * free list. - * - * The device lock must be held when calling this function. - */ -static void gs_reset_config(struct gs_dev *dev) -{ - struct usb_request *req; - - if (dev == NULL) { - pr_err("gs_reset_config: NULL device pointer\n"); - return; - } - - if (dev->dev_config == GS_NO_CONFIG_ID) - return; - - dev->dev_config = GS_NO_CONFIG_ID; - - /* free write requests on the free list */ - while(!list_empty(&dev->dev_req_list)) { - req = list_entry(dev->dev_req_list.next, - struct usb_request, list); - list_del(&req->list); - gs_free_req(dev->dev_in_ep, req); - } - - /* disable endpoints, forcing completion of pending i/o; */ - /* completion handlers free their requests in this case */ - if (dev->dev_notify_ep) - usb_ep_disable(dev->dev_notify_ep); - usb_ep_disable(dev->dev_in_ep); - usb_ep_disable(dev->dev_out_ep); -} - -/* - * gs_build_config_buf - * - * Builds the config descriptors in the given buffer and returns the - * length, or a negative error number. - */ -static int gs_build_config_buf(u8 *buf, struct usb_gadget *g, - u8 type, unsigned int index, int is_otg) -{ - int len; - int high_speed = 0; - const struct usb_config_descriptor *config_desc; - const struct usb_descriptor_header **function; - - if (index >= gs_device_desc.bNumConfigurations) - return -EINVAL; - - /* other speed switches high and full speed */ - if (gadget_is_dualspeed(g)) { - high_speed = (g->speed == USB_SPEED_HIGH); - if (type == USB_DT_OTHER_SPEED_CONFIG) - high_speed = !high_speed; - } - if (use_acm) { - config_desc = &gs_acm_config_desc; - function = high_speed - ? gs_acm_highspeed_function - : gs_acm_fullspeed_function; + serial_config_driver.label = "CDC ACM config"; + serial_config_driver.bConfigurationValue = 2; + device_desc.bDeviceClass = USB_CLASS_COMM; + device_desc.idProduct = + __constant_cpu_to_le16(GS_CDC_PRODUCT_ID); } else { - config_desc = &gs_bulk_config_desc; - function = high_speed - ? gs_bulk_highspeed_function - : gs_bulk_fullspeed_function; - } - - /* for now, don't advertise srp-only devices */ - if (!is_otg) - function++; - - len = usb_gadget_config_buf(config_desc, buf, GS_MAX_DESC_LEN, function); - if (len < 0) - return len; - - ((struct usb_config_descriptor *)buf)->bDescriptorType = type; - - return len; -} - -/* - * gs_alloc_req - * - * Allocate a usb_request and its buffer. Returns a pointer to the - * usb_request or NULL if there is an error. - */ -static struct usb_request * -gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags) -{ - struct usb_request *req; - - if (ep == NULL) - return NULL; - - req = usb_ep_alloc_request(ep, kmalloc_flags); - - if (req != NULL) { - req->length = len; - req->buf = kmalloc(len, kmalloc_flags); - if (req->buf == NULL) { - usb_ep_free_request(ep, req); - return NULL; - } + serial_config_driver.label = "Generic Serial config"; + serial_config_driver.bConfigurationValue = 1; + device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; + device_desc.idProduct = + __constant_cpu_to_le16(GS_PRODUCT_ID); } + strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label; - return req; + return usb_composite_register(&gserial_driver); } +module_init(init); -/* - * gs_free_req - * - * Free a usb_request and its buffer. - */ -static void gs_free_req(struct usb_ep *ep, struct usb_request *req) +static void __exit cleanup(void) { - if (ep != NULL && req != NULL) { - kfree(req->buf); - usb_ep_free_request(ep, req); - } -} - -/* - * gs_alloc_ports - * - * Allocate all ports and set the gs_dev struct to point to them. - * Return 0 if successful, or a negative error number. - * - * The device lock is normally held when calling this function. - */ -static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags) -{ - int i; - struct gs_port *port; - - if (dev == NULL) - return -EIO; - - for (i=0; i<GS_NUM_PORTS; i++) { - if ((port=kzalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL) - return -ENOMEM; - - port->port_dev = dev; - port->port_num = i; - port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE); - port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT; - port->port_line_coding.bParityType = GS_DEFAULT_PARITY; - port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS; - spin_lock_init(&port->port_lock); - init_waitqueue_head(&port->port_write_wait); - - dev->dev_port[i] = port; - } - - return 0; -} - -/* - * gs_free_ports - * - * Free all closed ports. Open ports are disconnected by - * freeing their write buffers, setting their device pointers - * and the pointers to them in the device to NULL. These - * ports will be freed when closed. - * - * The device lock is normally held when calling this function. - */ -static void gs_free_ports(struct gs_dev *dev) -{ - int i; - unsigned long flags; - struct gs_port *port; - - if (dev == NULL) - return; - - for (i=0; i<GS_NUM_PORTS; i++) { - if ((port=dev->dev_port[i]) != NULL) { - dev->dev_port[i] = NULL; - - spin_lock_irqsave(&port->port_lock, flags); - - if (port->port_write_buf != NULL) { - gs_buf_free(port->port_write_buf); - port->port_write_buf = NULL; - } - - if (port->port_open_count > 0 || port->port_in_use) { - port->port_dev = NULL; - wake_up_interruptible(&port->port_write_wait); - if (port->port_tty) { - tty_hangup(port->port_tty); - } - spin_unlock_irqrestore(&port->port_lock, flags); - } else { - spin_unlock_irqrestore(&port->port_lock, flags); - kfree(port); - } - - } - } -} - -/*-------------------------------------------------------------------------*/ - -/* Circular Buffer */ - -/* - * gs_buf_alloc - * - * Allocate a circular buffer and all associated memory. - */ -static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags) -{ - struct gs_buf *gb; - - if (size == 0) - return NULL; - - gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags); - if (gb == NULL) - return NULL; - - gb->buf_buf = kmalloc(size, kmalloc_flags); - if (gb->buf_buf == NULL) { - kfree(gb); - return NULL; - } - - gb->buf_size = size; - gb->buf_get = gb->buf_put = gb->buf_buf; - - return gb; -} - -/* - * gs_buf_free - * - * Free the buffer and all associated memory. - */ -static void gs_buf_free(struct gs_buf *gb) -{ - if (gb) { - kfree(gb->buf_buf); - kfree(gb); - } -} - -/* - * gs_buf_clear - * - * Clear out all data in the circular buffer. - */ -static void gs_buf_clear(struct gs_buf *gb) -{ - if (gb != NULL) - gb->buf_get = gb->buf_put; - /* equivalent to a get of all data available */ -} - -/* - * gs_buf_data_avail - * - * Return the number of bytes of data available in the circular - * buffer. - */ -static unsigned int gs_buf_data_avail(struct gs_buf *gb) -{ - if (gb != NULL) - return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size; - else - return 0; -} - -/* - * gs_buf_space_avail - * - * Return the number of bytes of space available in the circular - * buffer. - */ -static unsigned int gs_buf_space_avail(struct gs_buf *gb) -{ - if (gb != NULL) - return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size; - else - return 0; -} - -/* - * gs_buf_put - * - * Copy data data from a user buffer and put it into the circular buffer. - * Restrict to the amount of space available. - * - * Return the number of bytes copied. - */ -static unsigned int -gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count) -{ - unsigned int len; - - if (gb == NULL) - return 0; - - len = gs_buf_space_avail(gb); - if (count > len) - count = len; - - if (count == 0) - return 0; - - len = gb->buf_buf + gb->buf_size - gb->buf_put; - if (count > len) { - memcpy(gb->buf_put, buf, len); - memcpy(gb->buf_buf, buf+len, count - len); - gb->buf_put = gb->buf_buf + count - len; - } else { - memcpy(gb->buf_put, buf, count); - if (count < len) - gb->buf_put += count; - else /* count == len */ - gb->buf_put = gb->buf_buf; - } - - return count; -} - -/* - * gs_buf_get - * - * Get data from the circular buffer and copy to the given buffer. - * Restrict to the amount of data available. - * - * Return the number of bytes copied. - */ -static unsigned int -gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count) -{ - unsigned int len; - - if (gb == NULL) - return 0; - - len = gs_buf_data_avail(gb); - if (count > len) - count = len; - - if (count == 0) - return 0; - - len = gb->buf_buf + gb->buf_size - gb->buf_get; - if (count > len) { - memcpy(buf, gb->buf_get, len); - memcpy(buf+len, gb->buf_buf, count - len); - gb->buf_get = gb->buf_buf + count - len; - } else { - memcpy(buf, gb->buf_get, count); - if (count < len) - gb->buf_get += count; - else /* count == len */ - gb->buf_get = gb->buf_buf; - } - - return count; -} - -/*-------------------------------------------------------------------------*/ - -static struct tty_driver *gs_tty_driver; - -/* - * gs_module_init - * - * Register as a USB gadget driver and a tty driver. - */ -static int __init gs_module_init(void) -{ - int i; - int retval; - - retval = usb_gadget_register_driver(&gs_gadget_driver); - if (retval) { - pr_err("gs_module_init: cannot register gadget driver, " - "ret=%d\n", retval); - return retval; - } - - gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS); - if (!gs_tty_driver) - return -ENOMEM; - gs_tty_driver->owner = THIS_MODULE; - gs_tty_driver->driver_name = GS_SHORT_NAME; - gs_tty_driver->name = "ttygs"; - gs_tty_driver->major = GS_MAJOR; - gs_tty_driver->minor_start = GS_MINOR_START; - gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; - gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - gs_tty_driver->init_termios = tty_std_termios; - /* must match GS_DEFAULT_DTE_RATE and friends */ - gs_tty_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - gs_tty_driver->init_termios.c_ispeed = GS_DEFAULT_DTE_RATE; - gs_tty_driver->init_termios.c_ospeed = GS_DEFAULT_DTE_RATE; - tty_set_operations(gs_tty_driver, &gs_tty_ops); - - for (i = 0; i < GS_NUM_PORTS; i++) - mutex_init(&gs_open_close_lock[i]); - - retval = tty_register_driver(gs_tty_driver); - if (retval) { - usb_gadget_unregister_driver(&gs_gadget_driver); - put_tty_driver(gs_tty_driver); - pr_err("gs_module_init: cannot register tty driver, " - "ret=%d\n", retval); - return retval; - } - - pr_info("gs_module_init: %s %s loaded\n", - GS_LONG_NAME, GS_VERSION_STR); - return 0; -} -module_init(gs_module_init); - -/* - * gs_module_exit - * - * Unregister as a tty driver and a USB gadget driver. - */ -static void __exit gs_module_exit(void) -{ - tty_unregister_driver(gs_tty_driver); - put_tty_driver(gs_tty_driver); - usb_gadget_unregister_driver(&gs_gadget_driver); - - pr_info("gs_module_exit: %s %s unloaded\n", - GS_LONG_NAME, GS_VERSION_STR); + usb_composite_unregister(&gserial_driver); + gserial_cleanup(); } -module_exit(gs_module_exit); +module_exit(cleanup); diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c new file mode 100644 index 000000000000..5458f43a8668 --- /dev/null +++ b/drivers/usb/gadget/u_ether.c @@ -0,0 +1,967 @@ +/* + * u_ether.c -- Ethernet-over-USB link layer utilities for Gadget stack + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/utsname.h> +#include <linux/device.h> +#include <linux/ctype.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> + +#include "u_ether.h" + + +/* + * This component encapsulates the Ethernet link glue needed to provide + * one (!) network link through the USB gadget stack, normally "usb0". + * + * The control and data models are handled by the function driver which + * connects to this code; such as CDC Ethernet, "CDC Subset", or RNDIS. + * That includes all descriptor and endpoint management. + * + * Link level addressing is handled by this component using module + * parameters; if no such parameters are provided, random link level + * addresses are used. Each end of the link uses one address. The + * host end address is exported in various ways, and is often recorded + * in configuration databases. + * + * The driver which assembles each configuration using such a link is + * responsible for ensuring that each configuration includes at most one + * instance of is network link. (The network layer provides ways for + * this single "physical" link to be used by multiple virtual links.) + */ + +#define DRIVER_VERSION "29-May-2008" + +struct eth_dev { + /* lock is held while accessing port_usb + * or updating its backlink port_usb->ioport + */ + spinlock_t lock; + struct gether *port_usb; + + struct net_device *net; + struct usb_gadget *gadget; + + spinlock_t req_lock; /* guard {rx,tx}_reqs */ + struct list_head tx_reqs, rx_reqs; + atomic_t tx_qlen; + + unsigned header_len; + struct sk_buff *(*wrap)(struct sk_buff *skb); + int (*unwrap)(struct sk_buff *skb); + + struct work_struct work; + + unsigned long todo; +#define WORK_RX_MEMORY 0 + + bool zlp; + u8 host_mac[ETH_ALEN]; +}; + +/*-------------------------------------------------------------------------*/ + +#define RX_EXTRA 20 /* bytes guarding against rx overflows */ + +#define DEFAULT_QLEN 2 /* double buffering by default */ + + +#ifdef CONFIG_USB_GADGET_DUALSPEED + +static unsigned qmult = 5; +module_param(qmult, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(qmult, "queue length multiplier at high speed"); + +#else /* full speed (low speed doesn't do bulk) */ +#define qmult 1 +#endif + +/* for dual-speed hardware, use deeper queues at highspeed */ +static inline int qlen(struct usb_gadget *gadget) +{ + if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH) + return qmult * DEFAULT_QLEN; + else + return DEFAULT_QLEN; +} + +/*-------------------------------------------------------------------------*/ + +/* REVISIT there must be a better way than having two sets + * of debug calls ... + */ + +#undef DBG +#undef VDBG +#undef ERROR +#undef WARN +#undef INFO + +#define xprintk(d, level, fmt, args...) \ + printk(level "%s: " fmt , (d)->net->name , ## args) + +#ifdef DEBUG +#undef DEBUG +#define DBG(dev, fmt, args...) \ + xprintk(dev , KERN_DEBUG , fmt , ## args) +#else +#define DBG(dev, fmt, args...) \ + do { } while (0) +#endif /* DEBUG */ + +#ifdef VERBOSE_DEBUG +#define VDBG DBG +#else +#define VDBG(dev, fmt, args...) \ + do { } while (0) +#endif /* DEBUG */ + +#define ERROR(dev, fmt, args...) \ + xprintk(dev , KERN_ERR , fmt , ## args) +#define WARN(dev, fmt, args...) \ + xprintk(dev , KERN_WARNING , fmt , ## args) +#define INFO(dev, fmt, args...) \ + xprintk(dev , KERN_INFO , fmt , ## args) + +/*-------------------------------------------------------------------------*/ + +/* NETWORK DRIVER HOOKUP (to the layer above this driver) */ + +static int eth_change_mtu(struct net_device *net, int new_mtu) +{ + struct eth_dev *dev = netdev_priv(net); + unsigned long flags; + int status = 0; + + /* don't change MTU on "live" link (peer won't know) */ + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) + status = -EBUSY; + else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN) + status = -ERANGE; + else + net->mtu = new_mtu; + spin_unlock_irqrestore(&dev->lock, flags); + + return status; +} + +static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) +{ + struct eth_dev *dev = netdev_priv(net); + + strlcpy(p->driver, "g_ether", sizeof p->driver); + strlcpy(p->version, DRIVER_VERSION, sizeof p->version); + strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version); + strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info); +} + +static u32 eth_get_link(struct net_device *net) +{ + struct eth_dev *dev = netdev_priv(net); + return dev->gadget->speed != USB_SPEED_UNKNOWN; +} + +/* REVISIT can also support: + * - WOL (by tracking suspends and issuing remote wakeup) + * - msglevel (implies updated messaging) + * - ... probably more ethtool ops + */ + +static struct ethtool_ops ops = { + .get_drvinfo = eth_get_drvinfo, + .get_link = eth_get_link +}; + +static void defer_kevent(struct eth_dev *dev, int flag) +{ + if (test_and_set_bit(flag, &dev->todo)) + return; + if (!schedule_work(&dev->work)) + ERROR(dev, "kevent %d may have been dropped\n", flag); + else + DBG(dev, "kevent %d scheduled\n", flag); +} + +static void rx_complete(struct usb_ep *ep, struct usb_request *req); + +static int +rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) +{ + struct sk_buff *skb; + int retval = -ENOMEM; + size_t size = 0; + struct usb_ep *out; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) + out = dev->port_usb->out_ep; + else + out = NULL; + spin_unlock_irqrestore(&dev->lock, flags); + + if (!out) + return -ENOTCONN; + + + /* Padding up to RX_EXTRA handles minor disagreements with host. + * Normally we use the USB "terminate on short read" convention; + * so allow up to (N*maxpacket), since that memory is normally + * already allocated. Some hardware doesn't deal well with short + * reads (e.g. DMA must be N*maxpacket), so for now don't trim a + * byte off the end (to force hardware errors on overflow). + * + * RNDIS uses internal framing, and explicitly allows senders to + * pad to end-of-packet. That's potentially nice for speed, but + * means receivers can't recover lost synch on their own (because + * new packets don't only start after a short RX). + */ + size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA; + size += dev->port_usb->header_len; + size += out->maxpacket - 1; + size -= size % out->maxpacket; + + skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); + if (skb == NULL) { + DBG(dev, "no rx skb\n"); + goto enomem; + } + + /* Some platforms perform better when IP packets are aligned, + * but on at least one, checksumming fails otherwise. Note: + * RNDIS headers involve variable numbers of LE32 values. + */ + skb_reserve(skb, NET_IP_ALIGN); + + req->buf = skb->data; + req->length = size; + req->complete = rx_complete; + req->context = skb; + + retval = usb_ep_queue(out, req, gfp_flags); + if (retval == -ENOMEM) +enomem: + defer_kevent(dev, WORK_RX_MEMORY); + if (retval) { + DBG(dev, "rx submit --> %d\n", retval); + if (skb) + dev_kfree_skb_any(skb); + spin_lock_irqsave(&dev->req_lock, flags); + list_add(&req->list, &dev->rx_reqs); + spin_unlock_irqrestore(&dev->req_lock, flags); + } + return retval; +} + +static void rx_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct sk_buff *skb = req->context; + struct eth_dev *dev = ep->driver_data; + int status = req->status; + + switch (status) { + + /* normal completion */ + case 0: + skb_put(skb, req->actual); + if (dev->unwrap) + status = dev->unwrap(skb); + if (status < 0 + || ETH_HLEN > skb->len + || skb->len > ETH_FRAME_LEN) { + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + DBG(dev, "rx length %d\n", skb->len); + break; + } + + skb->protocol = eth_type_trans(skb, dev->net); + dev->net->stats.rx_packets++; + dev->net->stats.rx_bytes += skb->len; + + /* no buffer copies needed, unless hardware can't + * use skb buffers. + */ + status = netif_rx(skb); + skb = NULL; + break; + + /* software-driven interface shutdown */ + case -ECONNRESET: /* unlink */ + case -ESHUTDOWN: /* disconnect etc */ + VDBG(dev, "rx shutdown, code %d\n", status); + goto quiesce; + + /* for hardware automagic (such as pxa) */ + case -ECONNABORTED: /* endpoint reset */ + DBG(dev, "rx %s reset\n", ep->name); + defer_kevent(dev, WORK_RX_MEMORY); +quiesce: + dev_kfree_skb_any(skb); + goto clean; + + /* data overrun */ + case -EOVERFLOW: + dev->net->stats.rx_over_errors++; + /* FALLTHROUGH */ + + default: + dev->net->stats.rx_errors++; + DBG(dev, "rx status %d\n", status); + break; + } + + if (skb) + dev_kfree_skb_any(skb); + if (!netif_running(dev->net)) { +clean: + spin_lock(&dev->req_lock); + list_add(&req->list, &dev->rx_reqs); + spin_unlock(&dev->req_lock); + req = NULL; + } + if (req) + rx_submit(dev, req, GFP_ATOMIC); +} + +static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) +{ + unsigned i; + struct usb_request *req; + + if (!n) + return -ENOMEM; + + /* queue/recycle up to N requests */ + i = n; + list_for_each_entry(req, list, list) { + if (i-- == 0) + goto extra; + } + while (i--) { + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (!req) + return list_empty(list) ? -ENOMEM : 0; + list_add(&req->list, list); + } + return 0; + +extra: + /* free extras */ + for (;;) { + struct list_head *next; + + next = req->list.next; + list_del(&req->list); + usb_ep_free_request(ep, req); + + if (next == list) + break; + + req = container_of(next, struct usb_request, list); + } + return 0; +} + +static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n) +{ + int status; + + spin_lock(&dev->req_lock); + status = prealloc(&dev->tx_reqs, link->in_ep, n); + if (status < 0) + goto fail; + status = prealloc(&dev->rx_reqs, link->out_ep, n); + if (status < 0) + goto fail; + goto done; +fail: + DBG(dev, "can't alloc requests\n"); +done: + spin_unlock(&dev->req_lock); + return status; +} + +static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) +{ + struct usb_request *req; + unsigned long flags; + + /* fill unused rxq slots with some skb */ + spin_lock_irqsave(&dev->req_lock, flags); + while (!list_empty(&dev->rx_reqs)) { + req = container_of(dev->rx_reqs.next, + struct usb_request, list); + list_del_init(&req->list); + spin_unlock_irqrestore(&dev->req_lock, flags); + + if (rx_submit(dev, req, gfp_flags) < 0) { + defer_kevent(dev, WORK_RX_MEMORY); + return; + } + + spin_lock_irqsave(&dev->req_lock, flags); + } + spin_unlock_irqrestore(&dev->req_lock, flags); +} + +static void eth_work(struct work_struct *work) +{ + struct eth_dev *dev = container_of(work, struct eth_dev, work); + + if (test_and_clear_bit(WORK_RX_MEMORY, &dev->todo)) { + if (netif_running(dev->net)) + rx_fill(dev, GFP_KERNEL); + } + + if (dev->todo) + DBG(dev, "work done, flags = 0x%lx\n", dev->todo); +} + +static void tx_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct sk_buff *skb = req->context; + struct eth_dev *dev = ep->driver_data; + + switch (req->status) { + default: + dev->net->stats.tx_errors++; + VDBG(dev, "tx err %d\n", req->status); + /* FALLTHROUGH */ + case -ECONNRESET: /* unlink */ + case -ESHUTDOWN: /* disconnect etc */ + break; + case 0: + dev->net->stats.tx_bytes += skb->len; + } + dev->net->stats.tx_packets++; + + spin_lock(&dev->req_lock); + list_add(&req->list, &dev->tx_reqs); + spin_unlock(&dev->req_lock); + dev_kfree_skb_any(skb); + + atomic_dec(&dev->tx_qlen); + if (netif_carrier_ok(dev->net)) + netif_wake_queue(dev->net); +} + +static inline int is_promisc(u16 cdc_filter) +{ + return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS; +} + +static int eth_start_xmit(struct sk_buff *skb, struct net_device *net) +{ + struct eth_dev *dev = netdev_priv(net); + int length = skb->len; + int retval; + struct usb_request *req = NULL; + unsigned long flags; + struct usb_ep *in; + u16 cdc_filter; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) { + in = dev->port_usb->in_ep; + cdc_filter = dev->port_usb->cdc_filter; + } else { + in = NULL; + cdc_filter = 0; + } + spin_unlock_irqrestore(&dev->lock, flags); + + if (!in) { + dev_kfree_skb_any(skb); + return 0; + } + + /* apply outgoing CDC or RNDIS filters */ + if (!is_promisc(cdc_filter)) { + u8 *dest = skb->data; + + if (is_multicast_ether_addr(dest)) { + u16 type; + + /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host + * SET_ETHERNET_MULTICAST_FILTERS requests + */ + if (is_broadcast_ether_addr(dest)) + type = USB_CDC_PACKET_TYPE_BROADCAST; + else + type = USB_CDC_PACKET_TYPE_ALL_MULTICAST; + if (!(cdc_filter & type)) { + dev_kfree_skb_any(skb); + return 0; + } + } + /* ignores USB_CDC_PACKET_TYPE_DIRECTED */ + } + + spin_lock_irqsave(&dev->req_lock, flags); + /* + * this freelist can be empty if an interrupt triggered disconnect() + * and reconfigured the gadget (shutting down this queue) after the + * network stack decided to xmit but before we got the spinlock. + */ + if (list_empty(&dev->tx_reqs)) { + spin_unlock_irqrestore(&dev->req_lock, flags); + return 1; + } + + req = container_of(dev->tx_reqs.next, struct usb_request, list); + list_del(&req->list); + + /* temporarily stop TX queue when the freelist empties */ + if (list_empty(&dev->tx_reqs)) + netif_stop_queue(net); + spin_unlock_irqrestore(&dev->req_lock, flags); + + /* no buffer copies needed, unless the network stack did it + * or the hardware can't use skb buffers. + * or there's not enough space for extra headers we need + */ + if (dev->wrap) { + struct sk_buff *skb_new; + + skb_new = dev->wrap(skb); + if (!skb_new) + goto drop; + + dev_kfree_skb_any(skb); + skb = skb_new; + length = skb->len; + } + req->buf = skb->data; + req->context = skb; + req->complete = tx_complete; + + /* use zlp framing on tx for strict CDC-Ether conformance, + * though any robust network rx path ignores extra padding. + * and some hardware doesn't like to write zlps. + */ + req->zero = 1; + if (!dev->zlp && (length % in->maxpacket) == 0) + length++; + + req->length = length; + + /* throttle highspeed IRQ rate back slightly */ + if (gadget_is_dualspeed(dev->gadget)) + req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) + ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) + : 0; + + retval = usb_ep_queue(in, req, GFP_ATOMIC); + switch (retval) { + default: + DBG(dev, "tx queue err %d\n", retval); + break; + case 0: + net->trans_start = jiffies; + atomic_inc(&dev->tx_qlen); + } + + if (retval) { +drop: + dev->net->stats.tx_dropped++; + dev_kfree_skb_any(skb); + spin_lock_irqsave(&dev->req_lock, flags); + if (list_empty(&dev->tx_reqs)) + netif_start_queue(net); + list_add(&req->list, &dev->tx_reqs); + spin_unlock_irqrestore(&dev->req_lock, flags); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static void eth_start(struct eth_dev *dev, gfp_t gfp_flags) +{ + DBG(dev, "%s\n", __func__); + + /* fill the rx queue */ + rx_fill(dev, gfp_flags); + + /* and open the tx floodgates */ + atomic_set(&dev->tx_qlen, 0); + netif_wake_queue(dev->net); +} + +static int eth_open(struct net_device *net) +{ + struct eth_dev *dev = netdev_priv(net); + struct gether *link; + + DBG(dev, "%s\n", __func__); + if (netif_carrier_ok(dev->net)) + eth_start(dev, GFP_KERNEL); + + spin_lock_irq(&dev->lock); + link = dev->port_usb; + if (link && link->open) + link->open(link); + spin_unlock_irq(&dev->lock); + + return 0; +} + +static int eth_stop(struct net_device *net) +{ + struct eth_dev *dev = netdev_priv(net); + unsigned long flags; + + VDBG(dev, "%s\n", __func__); + netif_stop_queue(net); + + DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", + dev->net->stats.rx_packets, dev->net->stats.tx_packets, + dev->net->stats.rx_errors, dev->net->stats.tx_errors + ); + + /* ensure there are no more active requests */ + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) { + struct gether *link = dev->port_usb; + + if (link->close) + link->close(link); + + /* NOTE: we have no abort-queue primitive we could use + * to cancel all pending I/O. Instead, we disable then + * reenable the endpoints ... this idiom may leave toggle + * wrong, but that's a self-correcting error. + * + * REVISIT: we *COULD* just let the transfers complete at + * their own pace; the network stack can handle old packets. + * For the moment we leave this here, since it works. + */ + usb_ep_disable(link->in_ep); + usb_ep_disable(link->out_ep); + if (netif_carrier_ok(net)) { + DBG(dev, "host still using in/out endpoints\n"); + usb_ep_enable(link->in_ep, link->in); + usb_ep_enable(link->out_ep, link->out); + } + } + spin_unlock_irqrestore(&dev->lock, flags); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ +static char *dev_addr; +module_param(dev_addr, charp, S_IRUGO); +MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); + +/* this address is invisible to ifconfig */ +static char *host_addr; +module_param(host_addr, charp, S_IRUGO); +MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); + + +static u8 __init nibble(unsigned char c) +{ + if (isdigit(c)) + return c - '0'; + c = toupper(c); + if (isxdigit(c)) + return 10 + c - 'A'; + return 0; +} + +static int __init get_ether_addr(const char *str, u8 *dev_addr) +{ + if (str) { + unsigned i; + + for (i = 0; i < 6; i++) { + unsigned char num; + + if ((*str == '.') || (*str == ':')) + str++; + num = nibble(*str++) << 4; + num |= (nibble(*str++)); + dev_addr [i] = num; + } + if (is_valid_ether_addr(dev_addr)) + return 0; + } + random_ether_addr(dev_addr); + return 1; +} + +static struct eth_dev *the_dev; + + +/** + * gether_setup - initialize one ethernet-over-usb link + * @g: gadget to associated with these links + * @ethaddr: NULL, or a buffer in which the ethernet address of the + * host side of the link is recorded + * Context: may sleep + * + * This sets up the single network link that may be exported by a + * gadget driver using this framework. The link layer addresses are + * set up using module parameters. + * + * Returns negative errno, or zero on success + */ +int __init gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) +{ + struct eth_dev *dev; + struct net_device *net; + int status; + + if (the_dev) + return -EBUSY; + + net = alloc_etherdev(sizeof *dev); + if (!net) + return -ENOMEM; + + dev = netdev_priv(net); + spin_lock_init(&dev->lock); + spin_lock_init(&dev->req_lock); + INIT_WORK(&dev->work, eth_work); + INIT_LIST_HEAD(&dev->tx_reqs); + INIT_LIST_HEAD(&dev->rx_reqs); + + /* network device setup */ + dev->net = net; + strcpy(net->name, "usb%d"); + + if (get_ether_addr(dev_addr, net->dev_addr)) + dev_warn(&g->dev, + "using random %s ethernet address\n", "self"); + if (get_ether_addr(host_addr, dev->host_mac)) + dev_warn(&g->dev, + "using random %s ethernet address\n", "host"); + + if (ethaddr) + memcpy(ethaddr, dev->host_mac, ETH_ALEN); + + net->change_mtu = eth_change_mtu; + net->hard_start_xmit = eth_start_xmit; + net->open = eth_open; + net->stop = eth_stop; + /* watchdog_timeo, tx_timeout ... */ + /* set_multicast_list */ + SET_ETHTOOL_OPS(net, &ops); + + /* two kinds of host-initiated state changes: + * - iff DATA transfer is active, carrier is "on" + * - tx queueing enabled if open *and* carrier is "on" + */ + netif_stop_queue(net); + netif_carrier_off(net); + + dev->gadget = g; + SET_NETDEV_DEV(net, &g->dev); + + status = register_netdev(net); + if (status < 0) { + dev_dbg(&g->dev, "register_netdev failed, %d\n", status); + free_netdev(net); + } else { + DECLARE_MAC_BUF(tmp); + + INFO(dev, "MAC %s\n", print_mac(tmp, net->dev_addr)); + INFO(dev, "HOST MAC %s\n", print_mac(tmp, dev->host_mac)); + + the_dev = dev; + } + + return status; +} + +/** + * gether_cleanup - remove Ethernet-over-USB device + * Context: may sleep + * + * This is called to free all resources allocated by @gether_setup(). + */ +void gether_cleanup(void) +{ + if (!the_dev) + return; + + unregister_netdev(the_dev->net); + free_netdev(the_dev->net); + + /* assuming we used keventd, it must quiesce too */ + flush_scheduled_work(); + + the_dev = NULL; +} + + +/** + * gether_connect - notify network layer that USB link is active + * @link: the USB link, set up with endpoints, descriptors matching + * current device speed, and any framing wrapper(s) set up. + * Context: irqs blocked + * + * This is called to activate endpoints and let the network layer know + * the connection is active ("carrier detect"). It may cause the I/O + * queues to open and start letting network packets flow, but will in + * any case activate the endpoints so that they respond properly to the + * USB host. + * + * Verify net_device pointer returned using IS_ERR(). If it doesn't + * indicate some error code (negative errno), ep->driver_data values + * have been overwritten. + */ +struct net_device *gether_connect(struct gether *link) +{ + struct eth_dev *dev = the_dev; + int result = 0; + + if (!dev) + return ERR_PTR(-EINVAL); + + link->in_ep->driver_data = dev; + result = usb_ep_enable(link->in_ep, link->in); + if (result != 0) { + DBG(dev, "enable %s --> %d\n", + link->in_ep->name, result); + goto fail0; + } + + link->out_ep->driver_data = dev; + result = usb_ep_enable(link->out_ep, link->out); + if (result != 0) { + DBG(dev, "enable %s --> %d\n", + link->out_ep->name, result); + goto fail1; + } + + if (result == 0) + result = alloc_requests(dev, link, qlen(dev->gadget)); + + if (result == 0) { + dev->zlp = link->is_zlp_ok; + DBG(dev, "qlen %d\n", qlen(dev->gadget)); + + dev->header_len = link->header_len; + dev->unwrap = link->unwrap; + dev->wrap = link->wrap; + + spin_lock(&dev->lock); + dev->port_usb = link; + link->ioport = dev; + spin_unlock(&dev->lock); + + netif_carrier_on(dev->net); + if (netif_running(dev->net)) + eth_start(dev, GFP_ATOMIC); + + /* on error, disable any endpoints */ + } else { + (void) usb_ep_disable(link->out_ep); +fail1: + (void) usb_ep_disable(link->in_ep); + } +fail0: + /* caller is responsible for cleanup on error */ + if (result < 0) + return ERR_PTR(result); + return dev->net; +} + +/** + * gether_disconnect - notify network layer that USB link is inactive + * @link: the USB link, on which gether_connect() was called + * Context: irqs blocked + * + * This is called to deactivate endpoints and let the network layer know + * the connection went inactive ("no carrier"). + * + * On return, the state is as if gether_connect() had never been called. + * The endpoints are inactive, and accordingly without active USB I/O. + * Pointers to endpoint descriptors and endpoint private data are nulled. + */ +void gether_disconnect(struct gether *link) +{ + struct eth_dev *dev = link->ioport; + struct usb_request *req; + + WARN_ON(!dev); + if (!dev) + return; + + DBG(dev, "%s\n", __func__); + + netif_stop_queue(dev->net); + netif_carrier_off(dev->net); + + /* disable endpoints, forcing (synchronous) completion + * of all pending i/o. then free the request objects + * and forget about the endpoints. + */ + usb_ep_disable(link->in_ep); + spin_lock(&dev->req_lock); + while (!list_empty(&dev->tx_reqs)) { + req = container_of(dev->tx_reqs.next, + struct usb_request, list); + list_del(&req->list); + + spin_unlock(&dev->req_lock); + usb_ep_free_request(link->in_ep, req); + spin_lock(&dev->req_lock); + } + spin_unlock(&dev->req_lock); + link->in_ep->driver_data = NULL; + link->in = NULL; + + usb_ep_disable(link->out_ep); + spin_lock(&dev->req_lock); + while (!list_empty(&dev->rx_reqs)) { + req = container_of(dev->rx_reqs.next, + struct usb_request, list); + list_del(&req->list); + + spin_unlock(&dev->req_lock); + usb_ep_free_request(link->out_ep, req); + spin_lock(&dev->req_lock); + } + spin_unlock(&dev->req_lock); + link->out_ep->driver_data = NULL; + link->out = NULL; + + /* finish forgetting about this USB link episode */ + dev->header_len = 0; + dev->unwrap = NULL; + dev->wrap = NULL; + + spin_lock(&dev->lock); + dev->port_usb = NULL; + link->ioport = NULL; + spin_unlock(&dev->lock); +} diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h new file mode 100644 index 000000000000..0d1f7ae3b071 --- /dev/null +++ b/drivers/usb/gadget/u_ether.h @@ -0,0 +1,127 @@ +/* + * u_ether.h -- interface to USB gadget "ethernet link" utilities + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __U_ETHER_H +#define __U_ETHER_H + +#include <linux/err.h> +#include <linux/if_ether.h> +#include <linux/usb/composite.h> +#include <linux/usb/cdc.h> + +#include "gadget_chips.h" + + +/* + * This represents the USB side of an "ethernet" link, managed by a USB + * function which provides control and (maybe) framing. Two functions + * in different configurations could share the same ethernet link/netdev, + * using different host interaction models. + * + * There is a current limitation that only one instance of this link may + * be present in any given configuration. When that's a problem, network + * layer facilities can be used to package multiple logical links on this + * single "physical" one. + */ +struct gether { + struct usb_function func; + + /* updated by gether_{connect,disconnect} */ + struct eth_dev *ioport; + + /* endpoints handle full and/or high speeds */ + struct usb_ep *in_ep; + struct usb_ep *out_ep; + + /* descriptors match device speed at gether_connect() time */ + struct usb_endpoint_descriptor *in; + struct usb_endpoint_descriptor *out; + + bool is_zlp_ok; + + u16 cdc_filter; + + /* hooks for added framing, as needed for RNDIS and EEM. + * we currently don't support multiple frames per SKB. + */ + u32 header_len; + struct sk_buff *(*wrap)(struct sk_buff *skb); + int (*unwrap)(struct sk_buff *skb); + + /* called on network open/close */ + void (*open)(struct gether *); + void (*close)(struct gether *); +}; + +#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ + |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ + |USB_CDC_PACKET_TYPE_PROMISCUOUS \ + |USB_CDC_PACKET_TYPE_DIRECTED) + + +/* netdev setup/teardown as directed by the gadget driver */ +int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]); +void gether_cleanup(void); + +/* connect/disconnect is handled by individual functions */ +struct net_device *gether_connect(struct gether *); +void gether_disconnect(struct gether *); + +/* Some controllers can't support CDC Ethernet (ECM) ... */ +static inline bool can_support_ecm(struct usb_gadget *gadget) +{ + if (!gadget_supports_altsettings(gadget)) + return false; + + /* SA1100 can do ECM, *without* status endpoint ... but we'll + * only use it in non-ECM mode for backwards compatibility + * (and since we currently require a status endpoint) + */ + if (gadget_is_sa1100(gadget)) + return false; + + /* Everything else is *presumably* fine ... but this is a bit + * chancy, so be **CERTAIN** there are no hardware issues with + * your controller. Add it above if it can't handle CDC. + */ + return true; +} + +/* each configuration may bind one instance of an ethernet link */ +int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); +int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); + +#ifdef CONFIG_USB_ETH_RNDIS + +int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); + +#else + +static inline int +rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +{ + return 0; +} + +#endif + +#endif /* __U_ETHER_H */ diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c new file mode 100644 index 000000000000..abf9505d3a75 --- /dev/null +++ b/drivers/usb/gadget/u_serial.c @@ -0,0 +1,1246 @@ +/* + * u_serial.c - utilities for USB gadget "serial port"/TTY support + * + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This code also borrows from usbserial.c, which is + * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2000 Peter Berger (pberger@brimson.com) + * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com) + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * either version 2 of that License or (at your option) any later version. + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> + +#include "u_serial.h" + + +/* + * This component encapsulates the TTY layer glue needed to provide basic + * "serial port" functionality through the USB gadget stack. Each such + * port is exposed through a /dev/ttyGS* node. + * + * After initialization (gserial_setup), these TTY port devices stay + * available until they are removed (gserial_cleanup). Each one may be + * connected to a USB function (gserial_connect), or disconnected (with + * gserial_disconnect) when the USB host issues a config change event. + * Data can only flow when the port is connected to the host. + * + * A given TTY port can be made available in multiple configurations. + * For example, each one might expose a ttyGS0 node which provides a + * login application. In one case that might use CDC ACM interface 0, + * while another configuration might use interface 3 for that. The + * work to handle that (including descriptor management) is not part + * of this component. + * + * Configurations may expose more than one TTY port. For example, if + * ttyGS0 provides login service, then ttyGS1 might provide dialer access + * for a telephone or fax link. And ttyGS2 might be something that just + * needs a simple byte stream interface for some messaging protocol that + * is managed in userspace ... OBEX, PTP, and MTP have been mentioned. + */ + +/* + * gserial is the lifecycle interface, used by USB functions + * gs_port is the I/O nexus, used by the tty driver + * tty_struct links to the tty/filesystem framework + * + * gserial <---> gs_port ... links will be null when the USB link is + * inactive; managed by gserial_{connect,disconnect}(). + * gserial->ioport == usb_ep->driver_data ... gs_port + * gs_port->port_usb ... gserial + * + * gs_port <---> tty_struct ... links will be null when the TTY file + * isn't opened; managed by gs_open()/gs_close() + * gserial->port_tty ... tty_struct + * tty_struct->driver_data ... gserial + */ + +/* RX and TX queues can buffer QUEUE_SIZE packets before they hit the + * next layer of buffering. For TX that's a circular buffer; for RX + * consider it a NOP. A third layer is provided by the TTY code. + */ +#define QUEUE_SIZE 16 +#define WRITE_BUF_SIZE 8192 /* TX only */ + +/* circular buffer */ +struct gs_buf { + unsigned buf_size; + char *buf_buf; + char *buf_get; + char *buf_put; +}; + +/* + * The port structure holds info for each port, one for each minor number + * (and thus for each /dev/ node). + */ +struct gs_port { + spinlock_t port_lock; /* guard port_* access */ + + struct gserial *port_usb; + struct tty_struct *port_tty; + + unsigned open_count; + bool openclose; /* open/close in progress */ + u8 port_num; + + wait_queue_head_t close_wait; /* wait for last close */ + + struct list_head read_pool; + struct tasklet_struct push; + + struct list_head write_pool; + struct gs_buf port_write_buf; + wait_queue_head_t drain_wait; /* wait while writes drain */ + + /* REVISIT this state ... */ + struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ +}; + +/* increase N_PORTS if you need more */ +#define N_PORTS 4 +static struct portmaster { + struct mutex lock; /* protect open/close */ + struct gs_port *port; +} ports[N_PORTS]; +static unsigned n_ports; + +#define GS_CLOSE_TIMEOUT 15 /* seconds */ + + + +#ifdef VERBOSE_DEBUG +#define pr_vdebug(fmt, arg...) \ + pr_debug(fmt, ##arg) +#else +#define pr_vdebug(fmt, arg...) \ + ({ if (0) pr_debug(fmt, ##arg); }) +#endif + +/*-------------------------------------------------------------------------*/ + +/* Circular Buffer */ + +/* + * gs_buf_alloc + * + * Allocate a circular buffer and all associated memory. + */ +static int gs_buf_alloc(struct gs_buf *gb, unsigned size) +{ + gb->buf_buf = kmalloc(size, GFP_KERNEL); + if (gb->buf_buf == NULL) + return -ENOMEM; + + gb->buf_size = size; + gb->buf_put = gb->buf_buf; + gb->buf_get = gb->buf_buf; + + return 0; +} + +/* + * gs_buf_free + * + * Free the buffer and all associated memory. + */ +static void gs_buf_free(struct gs_buf *gb) +{ + kfree(gb->buf_buf); + gb->buf_buf = NULL; +} + +/* + * gs_buf_clear + * + * Clear out all data in the circular buffer. + */ +static void gs_buf_clear(struct gs_buf *gb) +{ + gb->buf_get = gb->buf_put; + /* equivalent to a get of all data available */ +} + +/* + * gs_buf_data_avail + * + * Return the number of bytes of data available in the circular + * buffer. + */ +static unsigned gs_buf_data_avail(struct gs_buf *gb) +{ + return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size; +} + +/* + * gs_buf_space_avail + * + * Return the number of bytes of space available in the circular + * buffer. + */ +static unsigned gs_buf_space_avail(struct gs_buf *gb) +{ + return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size; +} + +/* + * gs_buf_put + * + * Copy data data from a user buffer and put it into the circular buffer. + * Restrict to the amount of space available. + * + * Return the number of bytes copied. + */ +static unsigned +gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count) +{ + unsigned len; + + len = gs_buf_space_avail(gb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = gb->buf_buf + gb->buf_size - gb->buf_put; + if (count > len) { + memcpy(gb->buf_put, buf, len); + memcpy(gb->buf_buf, buf+len, count - len); + gb->buf_put = gb->buf_buf + count - len; + } else { + memcpy(gb->buf_put, buf, count); + if (count < len) + gb->buf_put += count; + else /* count == len */ + gb->buf_put = gb->buf_buf; + } + + return count; +} + +/* + * gs_buf_get + * + * Get data from the circular buffer and copy to the given buffer. + * Restrict to the amount of data available. + * + * Return the number of bytes copied. + */ +static unsigned +gs_buf_get(struct gs_buf *gb, char *buf, unsigned count) +{ + unsigned len; + + len = gs_buf_data_avail(gb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = gb->buf_buf + gb->buf_size - gb->buf_get; + if (count > len) { + memcpy(buf, gb->buf_get, len); + memcpy(buf+len, gb->buf_buf, count - len); + gb->buf_get = gb->buf_buf + count - len; + } else { + memcpy(buf, gb->buf_get, count); + if (count < len) + gb->buf_get += count; + else /* count == len */ + gb->buf_get = gb->buf_buf; + } + + return count; +} + +/*-------------------------------------------------------------------------*/ + +/* I/O glue between TTY (upper) and USB function (lower) driver layers */ + +/* + * gs_alloc_req + * + * Allocate a usb_request and its buffer. Returns a pointer to the + * usb_request or NULL if there is an error. + */ +static struct usb_request * +gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags) +{ + struct usb_request *req; + + req = usb_ep_alloc_request(ep, kmalloc_flags); + + if (req != NULL) { + req->length = len; + req->buf = kmalloc(len, kmalloc_flags); + if (req->buf == NULL) { + usb_ep_free_request(ep, req); + return NULL; + } + } + + return req; +} + +/* + * gs_free_req + * + * Free a usb_request and its buffer. + */ +static void gs_free_req(struct usb_ep *ep, struct usb_request *req) +{ + kfree(req->buf); + usb_ep_free_request(ep, req); +} + +/* + * gs_send_packet + * + * If there is data to send, a packet is built in the given + * buffer and the size is returned. If there is no data to + * send, 0 is returned. + * + * Called with port_lock held. + */ +static unsigned +gs_send_packet(struct gs_port *port, char *packet, unsigned size) +{ + unsigned len; + + len = gs_buf_data_avail(&port->port_write_buf); + if (len < size) + size = len; + if (size != 0) + size = gs_buf_get(&port->port_write_buf, packet, size); + return size; +} + +/* + * gs_start_tx + * + * This function finds available write requests, calls + * gs_send_packet to fill these packets with data, and + * continues until either there are no more write requests + * available or no more data to send. This function is + * run whenever data arrives or write requests are available. + * + * Context: caller owns port_lock; port_usb is non-null. + */ +static int gs_start_tx(struct gs_port *port) +/* +__releases(&port->port_lock) +__acquires(&port->port_lock) +*/ +{ + struct list_head *pool = &port->write_pool; + struct usb_ep *in = port->port_usb->in; + int status = 0; + bool do_tty_wake = false; + + while (!list_empty(pool)) { + struct usb_request *req; + int len; + + req = list_entry(pool->next, struct usb_request, list); + len = gs_send_packet(port, req->buf, in->maxpacket); + if (len == 0) { + wake_up_interruptible(&port->drain_wait); + break; + } + do_tty_wake = true; + + req->length = len; + list_del(&req->list); + +#ifdef VERBOSE_DEBUG + pr_debug("%s: %s, len=%d, 0x%02x 0x%02x 0x%02x ...\n", + __func__, in->name, len, *((u8 *)req->buf), + *((u8 *)req->buf+1), *((u8 *)req->buf+2)); +#endif + + /* Drop lock while we call out of driver; completions + * could be issued while we do so. Disconnection may + * happen too; maybe immediately before we queue this! + * + * NOTE that we may keep sending data for a while after + * the TTY closed (dev->ioport->port_tty is NULL). + */ + spin_unlock(&port->port_lock); + status = usb_ep_queue(in, req, GFP_ATOMIC); + spin_lock(&port->port_lock); + + if (status) { + pr_debug("%s: %s %s err %d\n", + __func__, "queue", in->name, status); + list_add(&req->list, pool); + break; + } + + /* abort immediately after disconnect */ + if (!port->port_usb) + break; + } + + if (do_tty_wake && port->port_tty) + tty_wakeup(port->port_tty); + return status; +} + +static void gs_rx_push(unsigned long _port) +{ + struct gs_port *port = (void *)_port; + struct tty_struct *tty = port->port_tty; + + /* With low_latency, tty_flip_buffer_push() doesn't put its + * real work through a workqueue, so the ldisc has a better + * chance to keep up with peak USB data rates. + */ + if (tty) { + tty_flip_buffer_push(tty); + wake_up_interruptible(&tty->read_wait); + } +} + +/* + * gs_recv_packet + * + * Called for each USB packet received. Reads the packet + * header and stuffs the data in the appropriate tty buffer. + * Returns 0 if successful, or a negative error number. + * + * Called during USB completion routine, on interrupt time. + * With port_lock. + */ +static int gs_recv_packet(struct gs_port *port, char *packet, unsigned size) +{ + unsigned len; + struct tty_struct *tty; + + /* I/O completions can continue for a while after close(), until the + * request queue empties. Just discard any data we receive, until + * something reopens this TTY ... as if there were no HW flow control. + */ + tty = port->port_tty; + if (tty == NULL) { + pr_vdebug("%s: ttyGS%d, after close\n", + __func__, port->port_num); + return -EIO; + } + + len = tty_insert_flip_string(tty, packet, size); + if (len > 0) + tasklet_schedule(&port->push); + if (len < size) + pr_debug("%s: ttyGS%d, drop %d bytes\n", + __func__, port->port_num, size - len); + return 0; +} + +/* + * Context: caller owns port_lock, and port_usb is set + */ +static unsigned gs_start_rx(struct gs_port *port) +/* +__releases(&port->port_lock) +__acquires(&port->port_lock) +*/ +{ + struct list_head *pool = &port->read_pool; + struct usb_ep *out = port->port_usb->out; + unsigned started = 0; + + while (!list_empty(pool)) { + struct usb_request *req; + int status; + struct tty_struct *tty; + + /* no more rx if closed or throttled */ + tty = port->port_tty; + if (!tty || test_bit(TTY_THROTTLED, &tty->flags)) + break; + + req = list_entry(pool->next, struct usb_request, list); + list_del(&req->list); + req->length = out->maxpacket; + + /* drop lock while we call out; the controller driver + * may need to call us back (e.g. for disconnect) + */ + spin_unlock(&port->port_lock); + status = usb_ep_queue(out, req, GFP_ATOMIC); + spin_lock(&port->port_lock); + + if (status) { + pr_debug("%s: %s %s err %d\n", + __func__, "queue", out->name, status); + list_add(&req->list, pool); + break; + } + started++; + + /* abort immediately after disconnect */ + if (!port->port_usb) + break; + } + return started; +} + +static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) +{ + int status; + struct gs_port *port = ep->driver_data; + + spin_lock(&port->port_lock); + list_add(&req->list, &port->read_pool); + + switch (req->status) { + case 0: + /* normal completion */ + status = gs_recv_packet(port, req->buf, req->actual); + if (status && status != -EIO) + pr_debug("%s: %s %s err %d\n", + __func__, "recv", ep->name, status); + gs_start_rx(port); + break; + + case -ESHUTDOWN: + /* disconnect */ + pr_vdebug("%s: %s shutdown\n", __func__, ep->name); + break; + + default: + /* presumably a transient fault */ + pr_warning("%s: unexpected %s status %d\n", + __func__, ep->name, req->status); + gs_start_rx(port); + break; + } + spin_unlock(&port->port_lock); +} + +static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct gs_port *port = ep->driver_data; + + spin_lock(&port->port_lock); + list_add(&req->list, &port->write_pool); + + switch (req->status) { + default: + /* presumably a transient fault */ + pr_warning("%s: unexpected %s status %d\n", + __func__, ep->name, req->status); + /* FALL THROUGH */ + case 0: + /* normal completion */ + gs_start_tx(port); + break; + + case -ESHUTDOWN: + /* disconnect */ + pr_vdebug("%s: %s shutdown\n", __func__, ep->name); + break; + } + + spin_unlock(&port->port_lock); +} + +static void gs_free_requests(struct usb_ep *ep, struct list_head *head) +{ + struct usb_request *req; + + while (!list_empty(head)) { + req = list_entry(head->next, struct usb_request, list); + list_del(&req->list); + gs_free_req(ep, req); + } +} + +static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head, + void (*fn)(struct usb_ep *, struct usb_request *)) +{ + int i; + struct usb_request *req; + + /* Pre-allocate up to QUEUE_SIZE transfers, but if we can't + * do quite that many this time, don't fail ... we just won't + * be as speedy as we might otherwise be. + */ + for (i = 0; i < QUEUE_SIZE; i++) { + req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC); + if (!req) + return list_empty(head) ? -ENOMEM : 0; + req->complete = fn; + list_add_tail(&req->list, head); + } + return 0; +} + +/** + * gs_start_io - start USB I/O streams + * @dev: encapsulates endpoints to use + * Context: holding port_lock; port_tty and port_usb are non-null + * + * We only start I/O when something is connected to both sides of + * this port. If nothing is listening on the host side, we may + * be pointlessly filling up our TX buffers and FIFO. + */ +static int gs_start_io(struct gs_port *port) +{ + struct list_head *head = &port->read_pool; + struct usb_ep *ep = port->port_usb->out; + int status; + unsigned started; + + /* Allocate RX and TX I/O buffers. We can't easily do this much + * earlier (with GFP_KERNEL) because the requests are coupled to + * endpoints, as are the packet sizes we'll be using. Different + * configurations may use different endpoints with a given port; + * and high speed vs full speed changes packet sizes too. + */ + status = gs_alloc_requests(ep, head, gs_read_complete); + if (status) + return status; + + status = gs_alloc_requests(port->port_usb->in, &port->write_pool, + gs_write_complete); + if (status) { + gs_free_requests(ep, head); + return status; + } + + /* queue read requests */ + started = gs_start_rx(port); + + /* unblock any pending writes into our circular buffer */ + if (started) { + tty_wakeup(port->port_tty); + } else { + gs_free_requests(ep, head); + gs_free_requests(port->port_usb->in, &port->write_pool); + } + + return started ? 0 : status; +} + +/*-------------------------------------------------------------------------*/ + +/* TTY Driver */ + +/* + * gs_open sets up the link between a gs_port and its associated TTY. + * That link is broken *only* by TTY close(), and all driver methods + * know that. + */ +static int gs_open(struct tty_struct *tty, struct file *file) +{ + int port_num = tty->index; + struct gs_port *port; + int status; + + if (port_num < 0 || port_num >= n_ports) + return -ENXIO; + + do { + mutex_lock(&ports[port_num].lock); + port = ports[port_num].port; + if (!port) + status = -ENODEV; + else { + spin_lock_irq(&port->port_lock); + + /* already open? Great. */ + if (port->open_count) { + status = 0; + port->open_count++; + + /* currently opening/closing? wait ... */ + } else if (port->openclose) { + status = -EBUSY; + + /* ... else we do the work */ + } else { + status = -EAGAIN; + port->openclose = true; + } + spin_unlock_irq(&port->port_lock); + } + mutex_unlock(&ports[port_num].lock); + + switch (status) { + default: + /* fully handled */ + return status; + case -EAGAIN: + /* must do the work */ + break; + case -EBUSY: + /* wait for EAGAIN task to finish */ + msleep(1); + /* REVISIT could have a waitchannel here, if + * concurrent open performance is important + */ + break; + } + } while (status != -EAGAIN); + + /* Do the "real open" */ + spin_lock_irq(&port->port_lock); + + /* allocate circular buffer on first open */ + if (port->port_write_buf.buf_buf == NULL) { + + spin_unlock_irq(&port->port_lock); + status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE); + spin_lock_irq(&port->port_lock); + + if (status) { + pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n", + port->port_num, tty, file); + port->openclose = false; + goto exit_unlock_port; + } + } + + /* REVISIT if REMOVED (ports[].port NULL), abort the open + * to let rmmod work faster (but this way isn't wrong). + */ + + /* REVISIT maybe wait for "carrier detect" */ + + tty->driver_data = port; + port->port_tty = tty; + + port->open_count = 1; + port->openclose = false; + + /* low_latency means ldiscs work in tasklet context, without + * needing a workqueue schedule ... easier to keep up. + */ + tty->low_latency = 1; + + /* if connected, start the I/O stream */ + if (port->port_usb) { + pr_debug("gs_open: start ttyGS%d\n", port->port_num); + gs_start_io(port); + + /* REVISIT for ACM, issue "network connected" event */ + } + + pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file); + + status = 0; + +exit_unlock_port: + spin_unlock_irq(&port->port_lock); + return status; +} + +static int gs_writes_finished(struct gs_port *p) +{ + int cond; + + /* return true on disconnect or empty buffer */ + spin_lock_irq(&p->port_lock); + cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf); + spin_unlock_irq(&p->port_lock); + + return cond; +} + +static void gs_close(struct tty_struct *tty, struct file *file) +{ + struct gs_port *port = tty->driver_data; + + spin_lock_irq(&port->port_lock); + + if (port->open_count != 1) { + if (port->open_count == 0) + WARN_ON(1); + else + --port->open_count; + goto exit; + } + + pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file); + + /* mark port as closing but in use; we can drop port lock + * and sleep if necessary + */ + port->openclose = true; + port->open_count = 0; + + if (port->port_usb) + /* REVISIT for ACM, issue "network disconnected" event */; + + /* wait for circular write buffer to drain, disconnect, or at + * most GS_CLOSE_TIMEOUT seconds; then discard the rest + */ + if (gs_buf_data_avail(&port->port_write_buf) > 0 + && port->port_usb) { + spin_unlock_irq(&port->port_lock); + wait_event_interruptible_timeout(port->drain_wait, + gs_writes_finished(port), + GS_CLOSE_TIMEOUT * HZ); + spin_lock_irq(&port->port_lock); + } + + /* Iff we're disconnected, there can be no I/O in flight so it's + * ok to free the circular buffer; else just scrub it. And don't + * let the push tasklet fire again until we're re-opened. + */ + if (port->port_usb == NULL) + gs_buf_free(&port->port_write_buf); + else + gs_buf_clear(&port->port_write_buf); + + tasklet_kill(&port->push); + + tty->driver_data = NULL; + port->port_tty = NULL; + + port->openclose = false; + + pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", + port->port_num, tty, file); + + wake_up_interruptible(&port->close_wait); +exit: + spin_unlock_irq(&port->port_lock); +} + +static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int status; + + pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n", + port->port_num, tty, count); + + spin_lock_irqsave(&port->port_lock, flags); + if (count) + count = gs_buf_put(&port->port_write_buf, buf, count); + /* treat count == 0 as flush_chars() */ + if (port->port_usb) + status = gs_start_tx(port); + spin_unlock_irqrestore(&port->port_lock, flags); + + return count; +} + +static int gs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int status; + + pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %p\n", + port->port_num, tty, ch, __builtin_return_address(0)); + + spin_lock_irqsave(&port->port_lock, flags); + status = gs_buf_put(&port->port_write_buf, &ch, 1); + spin_unlock_irqrestore(&port->port_lock, flags); + + return status; +} + +static void gs_flush_chars(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + + pr_vdebug("gs_flush_chars: (%d,%p)\n", port->port_num, tty); + + spin_lock_irqsave(&port->port_lock, flags); + if (port->port_usb) + gs_start_tx(port); + spin_unlock_irqrestore(&port->port_lock, flags); +} + +static int gs_write_room(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int room = 0; + + spin_lock_irqsave(&port->port_lock, flags); + if (port->port_usb) + room = gs_buf_space_avail(&port->port_write_buf); + spin_unlock_irqrestore(&port->port_lock, flags); + + pr_vdebug("gs_write_room: (%d,%p) room=%d\n", + port->port_num, tty, room); + + return room; +} + +static int gs_chars_in_buffer(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int chars = 0; + + spin_lock_irqsave(&port->port_lock, flags); + chars = gs_buf_data_avail(&port->port_write_buf); + spin_unlock_irqrestore(&port->port_lock, flags); + + pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n", + port->port_num, tty, chars); + + return chars; +} + +/* undo side effects of setting TTY_THROTTLED */ +static void gs_unthrottle(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + unsigned started = 0; + + spin_lock_irqsave(&port->port_lock, flags); + if (port->port_usb) + started = gs_start_rx(port); + spin_unlock_irqrestore(&port->port_lock, flags); + + pr_vdebug("gs_unthrottle: ttyGS%d, %d packets\n", + port->port_num, started); +} + +static const struct tty_operations gs_tty_ops = { + .open = gs_open, + .close = gs_close, + .write = gs_write, + .put_char = gs_put_char, + .flush_chars = gs_flush_chars, + .write_room = gs_write_room, + .chars_in_buffer = gs_chars_in_buffer, + .unthrottle = gs_unthrottle, +}; + +/*-------------------------------------------------------------------------*/ + +static struct tty_driver *gs_tty_driver; + +static int __init +gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding) +{ + struct gs_port *port; + + port = kzalloc(sizeof(struct gs_port), GFP_KERNEL); + if (port == NULL) + return -ENOMEM; + + spin_lock_init(&port->port_lock); + init_waitqueue_head(&port->close_wait); + init_waitqueue_head(&port->drain_wait); + + tasklet_init(&port->push, gs_rx_push, (unsigned long) port); + + INIT_LIST_HEAD(&port->read_pool); + INIT_LIST_HEAD(&port->write_pool); + + port->port_num = port_num; + port->port_line_coding = *coding; + + ports[port_num].port = port; + + return 0; +} + +/** + * gserial_setup - initialize TTY driver for one or more ports + * @g: gadget to associate with these ports + * @count: how many ports to support + * Context: may sleep + * + * The TTY stack needs to know in advance how many devices it should + * plan to manage. Use this call to set up the ports you will be + * exporting through USB. Later, connect them to functions based + * on what configuration is activated by the USB host; and disconnect + * them as appropriate. + * + * An example would be a two-configuration device in which both + * configurations expose port 0, but through different functions. + * One configuration could even expose port 1 while the other + * one doesn't. + * + * Returns negative errno or zero. + */ +int __init gserial_setup(struct usb_gadget *g, unsigned count) +{ + unsigned i; + struct usb_cdc_line_coding coding; + int status; + + if (count == 0 || count > N_PORTS) + return -EINVAL; + + gs_tty_driver = alloc_tty_driver(count); + if (!gs_tty_driver) + return -ENOMEM; + + gs_tty_driver->owner = THIS_MODULE; + gs_tty_driver->driver_name = "g_serial"; + gs_tty_driver->name = "ttyGS"; + /* uses dynamically assigned dev_t values */ + + gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; + gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + gs_tty_driver->init_termios = tty_std_termios; + + /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on + * MS-Windows. Otherwise, most of these flags shouldn't affect + * anything unless we were to actually hook up to a serial line. + */ + gs_tty_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + gs_tty_driver->init_termios.c_ispeed = 9600; + gs_tty_driver->init_termios.c_ospeed = 9600; + + coding.dwDTERate = __constant_cpu_to_le32(9600); + coding.bCharFormat = 8; + coding.bParityType = USB_CDC_NO_PARITY; + coding.bDataBits = USB_CDC_1_STOP_BITS; + + tty_set_operations(gs_tty_driver, &gs_tty_ops); + + /* make devices be openable */ + for (i = 0; i < count; i++) { + mutex_init(&ports[i].lock); + status = gs_port_alloc(i, &coding); + if (status) { + count = i; + goto fail; + } + } + n_ports = count; + + /* export the driver ... */ + status = tty_register_driver(gs_tty_driver); + if (status) { + put_tty_driver(gs_tty_driver); + pr_err("%s: cannot register, err %d\n", + __func__, status); + goto fail; + } + + /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */ + for (i = 0; i < count; i++) { + struct device *tty_dev; + + tty_dev = tty_register_device(gs_tty_driver, i, &g->dev); + if (IS_ERR(tty_dev)) + pr_warning("%s: no classdev for port %d, err %ld\n", + __func__, i, PTR_ERR(tty_dev)); + } + + pr_debug("%s: registered %d ttyGS* device%s\n", __func__, + count, (count == 1) ? "" : "s"); + + return status; +fail: + while (count--) + kfree(ports[count].port); + put_tty_driver(gs_tty_driver); + gs_tty_driver = NULL; + return status; +} + +static int gs_closed(struct gs_port *port) +{ + int cond; + + spin_lock_irq(&port->port_lock); + cond = (port->open_count == 0) && !port->openclose; + spin_unlock_irq(&port->port_lock); + return cond; +} + +/** + * gserial_cleanup - remove TTY-over-USB driver and devices + * Context: may sleep + * + * This is called to free all resources allocated by @gserial_setup(). + * Accordingly, it may need to wait until some open /dev/ files have + * closed. + * + * The caller must have issued @gserial_disconnect() for any ports + * that had previously been connected, so that there is never any + * I/O pending when it's called. + */ +void gserial_cleanup(void) +{ + unsigned i; + struct gs_port *port; + + if (!gs_tty_driver) + return; + + /* start sysfs and /dev/ttyGS* node removal */ + for (i = 0; i < n_ports; i++) + tty_unregister_device(gs_tty_driver, i); + + for (i = 0; i < n_ports; i++) { + /* prevent new opens */ + mutex_lock(&ports[i].lock); + port = ports[i].port; + ports[i].port = NULL; + mutex_unlock(&ports[i].lock); + + /* wait for old opens to finish */ + wait_event(port->close_wait, gs_closed(port)); + + WARN_ON(port->port_usb != NULL); + + kfree(port); + } + n_ports = 0; + + tty_unregister_driver(gs_tty_driver); + gs_tty_driver = NULL; + + pr_debug("%s: cleaned up ttyGS* support\n", __func__); +} + +/** + * gserial_connect - notify TTY I/O glue that USB link is active + * @gser: the function, set up with endpoints and descriptors + * @port_num: which port is active + * Context: any (usually from irq) + * + * This is called activate endpoints and let the TTY layer know that + * the connection is active ... not unlike "carrier detect". It won't + * necessarily start I/O queues; unless the TTY is held open by any + * task, there would be no point. However, the endpoints will be + * activated so the USB host can perform I/O, subject to basic USB + * hardware flow control. + * + * Caller needs to have set up the endpoints and USB function in @dev + * before calling this, as well as the appropriate (speed-specific) + * endpoint descriptors, and also have set up the TTY driver by calling + * @gserial_setup(). + * + * Returns negative errno or zero. + * On success, ep->driver_data will be overwritten. + */ +int gserial_connect(struct gserial *gser, u8 port_num) +{ + struct gs_port *port; + unsigned long flags; + int status; + + if (!gs_tty_driver || port_num >= n_ports) + return -ENXIO; + + /* we "know" gserial_cleanup() hasn't been called */ + port = ports[port_num].port; + + /* activate the endpoints */ + status = usb_ep_enable(gser->in, gser->in_desc); + if (status < 0) + return status; + gser->in->driver_data = port; + + status = usb_ep_enable(gser->out, gser->out_desc); + if (status < 0) + goto fail_out; + gser->out->driver_data = port; + + /* then tell the tty glue that I/O can work */ + spin_lock_irqsave(&port->port_lock, flags); + gser->ioport = port; + port->port_usb = gser; + + /* REVISIT unclear how best to handle this state... + * we don't really couple it with the Linux TTY. + */ + gser->port_line_coding = port->port_line_coding; + + /* REVISIT if waiting on "carrier detect", signal. */ + + /* REVISIT for ACM, issue "network connection" status notification: + * connected if open_count, else disconnected. + */ + + /* if it's already open, start I/O */ + if (port->open_count) { + pr_debug("gserial_connect: start ttyGS%d\n", port->port_num); + gs_start_io(port); + } + + spin_unlock_irqrestore(&port->port_lock, flags); + + return status; + +fail_out: + usb_ep_disable(gser->in); + gser->in->driver_data = NULL; + return status; +} + +/** + * gserial_disconnect - notify TTY I/O glue that USB link is inactive + * @gser: the function, on which gserial_connect() was called + * Context: any (usually from irq) + * + * This is called to deactivate endpoints and let the TTY layer know + * that the connection went inactive ... not unlike "hangup". + * + * On return, the state is as if gserial_connect() had never been called; + * there is no active USB I/O on these endpoints. + */ +void gserial_disconnect(struct gserial *gser) +{ + struct gs_port *port = gser->ioport; + unsigned long flags; + + if (!port) + return; + + /* tell the TTY glue not to do I/O here any more */ + spin_lock_irqsave(&port->port_lock, flags); + + /* REVISIT as above: how best to track this? */ + port->port_line_coding = gser->port_line_coding; + + port->port_usb = NULL; + gser->ioport = NULL; + if (port->open_count > 0 || port->openclose) { + wake_up_interruptible(&port->drain_wait); + if (port->port_tty) + tty_hangup(port->port_tty); + } + spin_unlock_irqrestore(&port->port_lock, flags); + + /* disable endpoints, aborting down any active I/O */ + usb_ep_disable(gser->out); + gser->out->driver_data = NULL; + + usb_ep_disable(gser->in); + gser->in->driver_data = NULL; + + /* finally, free any unused/unusable I/O buffers */ + spin_lock_irqsave(&port->port_lock, flags); + if (port->open_count == 0 && !port->openclose) + gs_buf_free(&port->port_write_buf); + gs_free_requests(gser->out, &port->read_pool); + gs_free_requests(gser->in, &port->write_pool); + spin_unlock_irqrestore(&port->port_lock, flags); +} diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h new file mode 100644 index 000000000000..7b561138f90e --- /dev/null +++ b/drivers/usb/gadget/u_serial.h @@ -0,0 +1,58 @@ +/* + * u_serial.h - interface to USB gadget "serial port"/TTY utilities + * + * Copyright (C) 2008 David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * either version 2 of that License or (at your option) any later version. + */ + +#ifndef __U_SERIAL_H +#define __U_SERIAL_H + +#include <linux/usb/composite.h> +#include <linux/usb/cdc.h> + +/* + * One non-multiplexed "serial" I/O port ... there can be several of these + * on any given USB peripheral device, if it provides enough endpoints. + * + * The "u_serial" utility component exists to do one thing: manage TTY + * style I/O using the USB peripheral endpoints listed here, including + * hookups to sysfs and /dev for each logical "tty" device. + * + * REVISIT need TTY --> USB event flow too, so ACM can report open/close + * as carrier detect events. Model after ECM. There's more ACM state too. + * + * REVISIT someday, allow multiplexing several TTYs over these endpoints. + */ +struct gserial { + struct usb_function func; + + /* port is managed by gserial_{connect,disconnect} */ + struct gs_port *ioport; + + struct usb_ep *in; + struct usb_ep *out; + struct usb_endpoint_descriptor *in_desc; + struct usb_endpoint_descriptor *out_desc; + + /* REVISIT avoid this CDC-ACM support harder ... */ + struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */ +}; + +/* port setup/teardown is handled by gadget driver */ +int gserial_setup(struct usb_gadget *g, unsigned n_ports); +void gserial_cleanup(void); + +/* connect/disconnect is handled by individual functions */ +int gserial_connect(struct gserial *, u8 port_num); +void gserial_disconnect(struct gserial *); + +/* functions are bound to configurations by a config or gadget driver */ +int acm_bind_config(struct usb_configuration *c, u8 port_num); +int gser_bind_config(struct usb_configuration *c, u8 port_num); + +#endif /* __U_SERIAL_H */ diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index fce4924dbbe8..aa0bd4f126a1 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -1,8 +1,8 @@ /* * zero.c -- Gadget Zero, for USB development * - * Copyright (C) 2003-2007 David Brownell - * All rights reserved. + * Copyright (C) 2003-2008 David Brownell + * Copyright (C) 2008 by Nokia Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,12 +30,7 @@ * * It supports two similar configurations. One sinks whatever the usb host * writes, and in return sources zeroes. The other loops whatever the host - * writes back, so the host can read it. Module options include: - * - * buflen=N default N=4096, buffer size used - * qlen=N default N=32, how many buffers in the loopback queue - * loopdefault default false, list loopback config first - * autoresume=N default N=0, seconds before triggering remote wakeup + * writes back, so the host can read it. * * Many drivers will only have one configuration, letting them be much * simpler if they also don't support high speed operation (like this @@ -47,94 +42,35 @@ * work with low capability USB controllers without four bulk endpoints. */ +/* + * driver assumes self-powered hardware, and + * has no way for users to trigger remote wakeup. + */ + /* #define VERBOSE_DEBUG */ #include <linux/kernel.h> #include <linux/utsname.h> #include <linux/device.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - +#include "g_zero.h" #include "gadget_chips.h" /*-------------------------------------------------------------------------*/ -#define DRIVER_VERSION "Earth Day 2008" +#define DRIVER_VERSION "Cinco de Mayo 2008" -static const char shortname[] = "zero"; static const char longname[] = "Gadget Zero"; -static const char source_sink[] = "source and sink data"; -static const char loopback[] = "loop input to output"; - -/*-------------------------------------------------------------------------*/ - -/* - * driver assumes self-powered hardware, and - * has no way for users to trigger remote wakeup. - * - * this version autoconfigures as much as possible, - * which is reasonable for most "bulk-only" drivers. - */ -static const char *EP_IN_NAME; /* source */ -static const char *EP_OUT_NAME; /* sink */ - -/*-------------------------------------------------------------------------*/ - -/* big enough to hold our biggest descriptor */ -#define USB_BUFSIZ 256 - -struct zero_dev { - spinlock_t lock; - struct usb_gadget *gadget; - struct usb_request *req; /* for control responses */ - - /* when configured, we have one of two configs: - * - source data (in to host) and sink it (out from host) - * - or loop it back (out from host back in to host) - */ - u8 config; - struct usb_ep *in_ep, *out_ep; - - /* autoresume timer */ - struct timer_list resume; -}; - -#define DBG(d, fmt, args...) \ - dev_dbg(&(d)->gadget->dev , fmt , ## args) -#define VDBG(d, fmt, args...) \ - dev_vdbg(&(d)->gadget->dev , fmt , ## args) -#define ERROR(d, fmt, args...) \ - dev_err(&(d)->gadget->dev , fmt , ## args) -#define WARN(d, fmt, args...) \ - dev_warn(&(d)->gadget->dev , fmt , ## args) -#define INFO(d, fmt, args...) \ - dev_info(&(d)->gadget->dev , fmt , ## args) - -/*-------------------------------------------------------------------------*/ - -static unsigned buflen = 4096; -static unsigned qlen = 32; -static unsigned pattern = 0; - -module_param(buflen, uint, S_IRUGO); -module_param(qlen, uint, S_IRUGO); -module_param(pattern, uint, S_IRUGO|S_IWUSR); - -/* - * if it's nonzero, autoresume says how many seconds to wait - * before trying to wake up the host after suspend. - */ -static unsigned autoresume = 0; -module_param(autoresume, uint, 0); +unsigned buflen = 4096; +module_param(buflen, uint, 0); /* * Normally the "loopback" configuration is second (index 1) so * it's not the default. Here's where to change that order, to - * work better with hosts where config changes are problematic. - * Or controllers (like superh) that only support one config. + * work better with hosts where config changes are problematic or + * controllers (like original superh) that only support one config. */ static int loopdefault = 0; module_param(loopdefault, bool, S_IRUGO|S_IWUSR); @@ -156,24 +92,6 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR); /*-------------------------------------------------------------------------*/ -/* - * DESCRIPTORS ... most are static, but strings and (full) - * configuration descriptors are built on demand. - */ - -#define STRING_MANUFACTURER 25 -#define STRING_PRODUCT 42 -#define STRING_SERIAL 101 -#define STRING_SOURCE_SINK 250 -#define STRING_LOOPBACK 251 - -/* - * This device advertises two configurations; these numbers work - * on a pxa250 as well as more flexible hardware. - */ -#define CONFIG_SOURCE_SINK 3 -#define CONFIG_LOOPBACK 2 - static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -183,248 +101,64 @@ static struct usb_device_descriptor device_desc = { .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), - .iManufacturer = STRING_MANUFACTURER, - .iProduct = STRING_PRODUCT, - .iSerialNumber = STRING_SERIAL, .bNumConfigurations = 2, }; -static struct usb_config_descriptor source_sink_config = { - .bLength = sizeof source_sink_config, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 1, - .bConfigurationValue = CONFIG_SOURCE_SINK, - .iConfiguration = STRING_SOURCE_SINK, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* self-powered */ -}; - -static struct usb_config_descriptor loopback_config = { - .bLength = sizeof loopback_config, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 1, - .bConfigurationValue = CONFIG_LOOPBACK, - .iConfiguration = STRING_LOOPBACK, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* self-powered */ -}; - +#ifdef CONFIG_USB_OTG static struct usb_otg_descriptor otg_descriptor = { .bLength = sizeof otg_descriptor, .bDescriptorType = USB_DT_OTG, - .bmAttributes = USB_OTG_SRP, -}; - -/* one interface in each configuration */ - -static const struct usb_interface_descriptor source_sink_intf = { - .bLength = sizeof source_sink_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .iInterface = STRING_SOURCE_SINK, -}; - -static const struct usb_interface_descriptor loopback_intf = { - .bLength = sizeof loopback_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .iInterface = STRING_LOOPBACK, -}; - -/* two full speed bulk endpoints; their use is config-dependent */ - -static struct usb_endpoint_descriptor fs_source_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_endpoint_descriptor fs_sink_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static const struct usb_descriptor_header *fs_source_sink_function[] = { - (struct usb_descriptor_header *) &otg_descriptor, - (struct usb_descriptor_header *) &source_sink_intf, - (struct usb_descriptor_header *) &fs_sink_desc, - (struct usb_descriptor_header *) &fs_source_desc, - NULL, -}; - -static const struct usb_descriptor_header *fs_loopback_function[] = { - (struct usb_descriptor_header *) &otg_descriptor, - (struct usb_descriptor_header *) &loopback_intf, - (struct usb_descriptor_header *) &fs_sink_desc, - (struct usb_descriptor_header *) &fs_source_desc, - NULL, -}; - -/* - * usb 2.0 devices need to expose both high speed and full speed - * descriptors, unless they only run at full speed. - * - * that means alternate endpoint descriptors (bigger packets) - * and a "device qualifier" ... plus more construction options - * for the config descriptor. - */ - -static struct usb_endpoint_descriptor hs_source_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor hs_sink_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_qualifier_descriptor dev_qualifier = { - .bLength = sizeof dev_qualifier, - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - - .bcdUSB = __constant_cpu_to_le16(0x0200), - .bDeviceClass = USB_CLASS_VENDOR_SPEC, - - .bNumConfigurations = 2, + /* REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, }; -static const struct usb_descriptor_header *hs_source_sink_function[] = { +const struct usb_descriptor_header *otg_desc[] = { (struct usb_descriptor_header *) &otg_descriptor, - (struct usb_descriptor_header *) &source_sink_intf, - (struct usb_descriptor_header *) &hs_source_desc, - (struct usb_descriptor_header *) &hs_sink_desc, NULL, }; +#endif -static const struct usb_descriptor_header *hs_loopback_function[] = { - (struct usb_descriptor_header *) &otg_descriptor, - (struct usb_descriptor_header *) &loopback_intf, - (struct usb_descriptor_header *) &hs_source_desc, - (struct usb_descriptor_header *) &hs_sink_desc, - NULL, -}; +/* string IDs are assigned dynamically */ -/* maxpacket and other transfer characteristics vary by speed. */ -static inline struct usb_endpoint_descriptor * -ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, - struct usb_endpoint_descriptor *fs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 +#define STRING_SERIAL_IDX 2 static char manufacturer[50]; /* default serial number takes at least two packets */ static char serial[] = "0123456789.0123456789.0123456789"; - -/* static strings, in UTF-8 */ -static struct usb_string strings[] = { - { STRING_MANUFACTURER, manufacturer, }, - { STRING_PRODUCT, longname, }, - { STRING_SERIAL, serial, }, - { STRING_LOOPBACK, loopback, }, - { STRING_SOURCE_SINK, source_sink, }, +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer, + [STRING_PRODUCT_IDX].s = longname, + [STRING_SERIAL_IDX].s = serial, { } /* end of list */ }; -static struct usb_gadget_strings stringtab = { +static struct usb_gadget_strings stringtab_dev = { .language = 0x0409, /* en-us */ - .strings = strings, + .strings = strings_dev, }; -/* - * config descriptors are also handcrafted. these must agree with code - * that sets configurations, and with code managing interfaces and their - * altsettings. other complexity may come from: - * - * - high speed support, including "other speed config" rules - * - multiple configurations - * - interfaces with alternate settings - * - embedded class or vendor-specific descriptors - * - * this handles high speed, and has a second config that could as easily - * have been an alternate interface setting (on most hardware). - * - * NOTE: to demonstrate (and test) more USB capabilities, this driver - * should include an altsetting to test interrupt transfers, including - * high bandwidth modes at high speed. (Maybe work like Intel's test - * device?) - */ -static int config_buf(struct usb_gadget *gadget, - u8 *buf, u8 type, unsigned index) -{ - int is_source_sink; - int len; - const struct usb_descriptor_header **function; - int hs = 0; - - /* two configurations will always be index 0 and index 1 */ - if (index > 1) - return -EINVAL; - is_source_sink = loopdefault ? (index == 1) : (index == 0); - - if (gadget_is_dualspeed(gadget)) { - hs = (gadget->speed == USB_SPEED_HIGH); - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - } - if (hs) - function = is_source_sink - ? hs_source_sink_function - : hs_loopback_function; - else - function = is_source_sink - ? fs_source_sink_function - : fs_loopback_function; - - /* for now, don't advertise srp-only devices */ - if (!gadget_is_otg(gadget)) - function++; - - len = usb_gadget_config_buf(is_source_sink - ? &source_sink_config - : &loopback_config, - buf, USB_BUFSIZ, function); - if (len < 0) - return len; - ((struct usb_config_descriptor *) buf)->bDescriptorType = type; - return len; -} +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, +}; /*-------------------------------------------------------------------------*/ -static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) +struct usb_request *alloc_ep_req(struct usb_ep *ep) { struct usb_request *req; req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (req) { - req->length = length; - req->buf = kmalloc(length, GFP_ATOMIC); + req->length = buflen; + req->buf = kmalloc(buflen, GFP_ATOMIC); if (!req->buf) { usb_ep_free_request(ep, req); req = NULL; @@ -433,681 +167,73 @@ static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) return req; } -static void free_ep_req(struct usb_ep *ep, struct usb_request *req) +void free_ep_req(struct usb_ep *ep, struct usb_request *req) { kfree(req->buf); usb_ep_free_request(ep, req); } -/*-------------------------------------------------------------------------*/ - -/* - * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripherals, - * this just sinks bulk packets OUT to the peripheral and sources them IN - * to the host, optionally with specific data patterns. - * - * In terms of control messaging, this supports all the standard requests - * plus two that support control-OUT tests. - * - * Note that because this doesn't queue more than one request at a time, - * some other function must be used to test queueing logic. The network - * link (g_ether) is probably the best option for that. - */ - -/* optionally require specific source/sink data patterns */ - -static int -check_read_data( - struct zero_dev *dev, - struct usb_ep *ep, - struct usb_request *req -) +static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) { - unsigned i; - u8 *buf = req->buf; - - for (i = 0; i < req->actual; i++, buf++) { - switch (pattern) { - /* all-zeroes has no synchronization issues */ - case 0: - if (*buf == 0) - continue; - break; - /* mod63 stays in sync with short-terminated transfers, - * or otherwise when host and gadget agree on how large - * each usb transfer request should be. resync is done - * with set_interface or set_config. - */ - case 1: - if (*buf == (u8)(i % 63)) - continue; - break; - } - ERROR(dev, "bad OUT byte, buf[%d] = %d\n", i, *buf); - usb_ep_set_halt(ep); - return -EINVAL; + int value; + + if (ep->driver_data) { + value = usb_ep_disable(ep); + if (value < 0) + DBG(cdev, "disable %s --> %d\n", + ep->name, value); + ep->driver_data = NULL; } - return 0; } -static void reinit_write_data(struct usb_ep *ep, struct usb_request *req) +void disable_endpoints(struct usb_composite_dev *cdev, + struct usb_ep *in, struct usb_ep *out) { - unsigned i; - u8 *buf = req->buf; - - switch (pattern) { - case 0: - memset(req->buf, 0, req->length); - break; - case 1: - for (i = 0; i < req->length; i++) - *buf++ = (u8) (i % 63); - break; - } -} - -/* if there is only one request in the queue, there'll always be an - * irq delay between end of one request and start of the next. - * that prevents using hardware dma queues. - */ -static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct zero_dev *dev = ep->driver_data; - int status = req->status; - - switch (status) { - - case 0: /* normal completion? */ - if (ep == dev->out_ep) { - check_read_data(dev, ep, req); - memset(req->buf, 0x55, req->length); - } else - reinit_write_data(ep, req); - break; - - /* this endpoint is normally active while we're configured */ - case -ECONNABORTED: /* hardware forced ep reset */ - case -ECONNRESET: /* request dequeued */ - case -ESHUTDOWN: /* disconnect from host */ - VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, - req->actual, req->length); - if (ep == dev->out_ep) - check_read_data(dev, ep, req); - free_ep_req(ep, req); - return; - - case -EOVERFLOW: /* buffer overrun on read means that - * we didn't provide a big enough - * buffer. - */ - default: -#if 1 - DBG(dev, "%s complete --> %d, %d/%d\n", ep->name, - status, req->actual, req->length); -#endif - case -EREMOTEIO: /* short read */ - break; - } - - status = usb_ep_queue(ep, req, GFP_ATOMIC); - if (status) { - ERROR(dev, "kill %s: resubmit %d bytes --> %d\n", - ep->name, req->length, status); - usb_ep_set_halt(ep); - /* FIXME recover later ... somehow */ - } -} - -static struct usb_request *source_sink_start_ep(struct usb_ep *ep) -{ - struct usb_request *req; - int status; - - req = alloc_ep_req(ep, buflen); - if (!req) - return NULL; - - memset(req->buf, 0, req->length); - req->complete = source_sink_complete; - - if (strcmp(ep->name, EP_IN_NAME) == 0) - reinit_write_data(ep, req); - else - memset(req->buf, 0x55, req->length); - - status = usb_ep_queue(ep, req, GFP_ATOMIC); - if (status) { - struct zero_dev *dev = ep->driver_data; - - ERROR(dev, "start %s --> %d\n", ep->name, status); - free_ep_req(ep, req); - req = NULL; - } - - return req; -} - -static int set_source_sink_config(struct zero_dev *dev) -{ - int result = 0; - struct usb_ep *ep; - struct usb_gadget *gadget = dev->gadget; - - gadget_for_each_ep(ep, gadget) { - const struct usb_endpoint_descriptor *d; - - /* one endpoint writes (sources) zeroes in (to the host) */ - if (strcmp(ep->name, EP_IN_NAME) == 0) { - d = ep_desc(gadget, &hs_source_desc, &fs_source_desc); - result = usb_ep_enable(ep, d); - if (result == 0) { - ep->driver_data = dev; - if (source_sink_start_ep(ep) != NULL) { - dev->in_ep = ep; - continue; - } - usb_ep_disable(ep); - result = -EIO; - } - - /* one endpoint reads (sinks) anything out (from the host) */ - } else if (strcmp(ep->name, EP_OUT_NAME) == 0) { - d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc); - result = usb_ep_enable(ep, d); - if (result == 0) { - ep->driver_data = dev; - if (source_sink_start_ep(ep) != NULL) { - dev->out_ep = ep; - continue; - } - usb_ep_disable(ep); - result = -EIO; - } - - /* ignore any other endpoints */ - } else - continue; - - /* stop on error */ - ERROR(dev, "can't start %s, result %d\n", ep->name, result); - break; - } - if (result == 0) - DBG(dev, "buflen %d\n", buflen); - - /* caller is responsible for cleanup on error */ - return result; -} - -/*-------------------------------------------------------------------------*/ - -static void loopback_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct zero_dev *dev = ep->driver_data; - int status = req->status; - - switch (status) { - - case 0: /* normal completion? */ - if (ep == dev->out_ep) { - /* loop this OUT packet back IN to the host */ - req->zero = (req->actual < req->length); - req->length = req->actual; - status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); - if (status == 0) - return; - - /* "should never get here" */ - ERROR(dev, "can't loop %s to %s: %d\n", - ep->name, dev->in_ep->name, - status); - } - - /* queue the buffer for some later OUT packet */ - req->length = buflen; - status = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC); - if (status == 0) - return; - - /* "should never get here" */ - /* FALLTHROUGH */ - - default: - ERROR(dev, "%s loop complete --> %d, %d/%d\n", ep->name, - status, req->actual, req->length); - /* FALLTHROUGH */ - - /* NOTE: since this driver doesn't maintain an explicit record - * of requests it submitted (just maintains qlen count), we - * rely on the hardware driver to clean up on disconnect or - * endpoint disable. - */ - case -ECONNABORTED: /* hardware forced ep reset */ - case -ECONNRESET: /* request dequeued */ - case -ESHUTDOWN: /* disconnect from host */ - free_ep_req(ep, req); - return; - } -} - -static int set_loopback_config(struct zero_dev *dev) -{ - int result = 0; - struct usb_ep *ep; - struct usb_gadget *gadget = dev->gadget; - - gadget_for_each_ep(ep, gadget) { - const struct usb_endpoint_descriptor *d; - - /* one endpoint writes data back IN to the host */ - if (strcmp(ep->name, EP_IN_NAME) == 0) { - d = ep_desc(gadget, &hs_source_desc, &fs_source_desc); - result = usb_ep_enable(ep, d); - if (result == 0) { - ep->driver_data = dev; - dev->in_ep = ep; - continue; - } - - /* one endpoint just reads OUT packets */ - } else if (strcmp(ep->name, EP_OUT_NAME) == 0) { - d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc); - result = usb_ep_enable(ep, d); - if (result == 0) { - ep->driver_data = dev; - dev->out_ep = ep; - continue; - } - - /* ignore any other endpoints */ - } else - continue; - - /* stop on error */ - ERROR(dev, "can't enable %s, result %d\n", ep->name, result); - break; - } - - /* allocate a bunch of read buffers and queue them all at once. - * we buffer at most 'qlen' transfers; fewer if any need more - * than 'buflen' bytes each. - */ - if (result == 0) { - struct usb_request *req; - unsigned i; - - ep = dev->out_ep; - for (i = 0; i < qlen && result == 0; i++) { - req = alloc_ep_req(ep, buflen); - if (req) { - req->complete = loopback_complete; - result = usb_ep_queue(ep, req, GFP_ATOMIC); - if (result) - DBG(dev, "%s queue req --> %d\n", - ep->name, result); - } else - result = -ENOMEM; - } - } - if (result == 0) - DBG(dev, "qlen %d, buflen %d\n", qlen, buflen); - - /* caller is responsible for cleanup on error */ - return result; -} - -/*-------------------------------------------------------------------------*/ - -static void zero_reset_config(struct zero_dev *dev) -{ - if (dev->config == 0) - return; - - DBG(dev, "reset config\n"); - - /* just disable endpoints, forcing completion of pending i/o. - * all our completion handlers free their requests in this case. - */ - if (dev->in_ep) { - usb_ep_disable(dev->in_ep); - dev->in_ep = NULL; - } - if (dev->out_ep) { - usb_ep_disable(dev->out_ep); - dev->out_ep = NULL; - } - dev->config = 0; - del_timer(&dev->resume); -} - -/* change our operational config. this code must agree with the code - * that returns config descriptors, and altsetting code. - * - * it's also responsible for power management interactions. some - * configurations might not work with our current power sources. - * - * note that some device controller hardware will constrain what this - * code can do, perhaps by disallowing more than one configuration or - * by limiting configuration choices (like the pxa2xx). - */ -static int zero_set_config(struct zero_dev *dev, unsigned number) -{ - int result = 0; - struct usb_gadget *gadget = dev->gadget; - - if (number == dev->config) - return 0; - - if (gadget_is_sa1100(gadget) && dev->config) { - /* tx fifo is full, but we can't clear it...*/ - ERROR(dev, "can't change configurations\n"); - return -ESPIPE; - } - zero_reset_config(dev); - - switch (number) { - case CONFIG_SOURCE_SINK: - result = set_source_sink_config(dev); - break; - case CONFIG_LOOPBACK: - result = set_loopback_config(dev); - break; - default: - result = -EINVAL; - /* FALL THROUGH */ - case 0: - return result; - } - - if (!result && (!dev->in_ep || !dev->out_ep)) - result = -ENODEV; - if (result) - zero_reset_config(dev); - else { - char *speed; - - switch (gadget->speed) { - case USB_SPEED_LOW: speed = "low"; break; - case USB_SPEED_FULL: speed = "full"; break; - case USB_SPEED_HIGH: speed = "high"; break; - default: speed = "?"; break; - } - - dev->config = number; - INFO(dev, "%s speed config #%d: %s\n", speed, number, - (number == CONFIG_SOURCE_SINK) - ? source_sink : loopback); - } - return result; -} - -/*-------------------------------------------------------------------------*/ - -static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - DBG((struct zero_dev *) ep->driver_data, - "setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - -/* - * The setup() callback implements all the ep0 functionality that's - * not handled lower down, in hardware or the hardware driver (like - * device and endpoint feature flags, and their status). It's all - * housekeeping for the gadget function we're implementing. Most of - * the work is in config-specific setup. - */ -static int -zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) -{ - struct zero_dev *dev = get_gadget_data(gadget); - struct usb_request *req = dev->req; - int value = -EOPNOTSUPP; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - - /* usually this stores reply data in the pre-allocated ep0 buffer, - * but config change events will reconfigure hardware. - */ - req->zero = 0; - switch (ctrl->bRequest) { - - case USB_REQ_GET_DESCRIPTOR: - if (ctrl->bRequestType != USB_DIR_IN) - goto unknown; - switch (w_value >> 8) { - - case USB_DT_DEVICE: - value = min(w_length, (u16) sizeof device_desc); - memcpy(req->buf, &device_desc, value); - break; - case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) - break; - value = min(w_length, (u16) sizeof dev_qualifier); - memcpy(req->buf, &dev_qualifier, value); - break; - - case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) - break; - // FALLTHROUGH - case USB_DT_CONFIG: - value = config_buf(gadget, req->buf, - w_value >> 8, - w_value & 0xff); - if (value >= 0) - value = min(w_length, (u16) value); - break; - - case USB_DT_STRING: - /* wIndex == language code. - * this driver only handles one language, you can - * add string tables for other languages, using - * any UTF-8 characters - */ - value = usb_gadget_get_string(&stringtab, - w_value & 0xff, req->buf); - if (value >= 0) - value = min(w_length, (u16) value); - break; - } - break; - - /* currently two configs, two speeds */ - case USB_REQ_SET_CONFIGURATION: - if (ctrl->bRequestType != 0) - goto unknown; - if (gadget->a_hnp_support) - DBG(dev, "HNP available\n"); - else if (gadget->a_alt_hnp_support) - DBG(dev, "HNP needs a different root port\n"); - else - VDBG(dev, "HNP inactive\n"); - spin_lock(&dev->lock); - value = zero_set_config(dev, w_value); - spin_unlock(&dev->lock); - break; - case USB_REQ_GET_CONFIGURATION: - if (ctrl->bRequestType != USB_DIR_IN) - goto unknown; - *(u8 *)req->buf = dev->config; - value = min(w_length, (u16) 1); - break; - - /* until we add altsetting support, or other interfaces, - * only 0/0 are possible. pxa2xx only supports 0/0 (poorly) - * and already killed pending endpoint I/O. - */ - case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE) - goto unknown; - spin_lock(&dev->lock); - if (dev->config && w_index == 0 && w_value == 0) { - u8 config = dev->config; - - /* resets interface configuration, forgets about - * previous transaction state (queued bufs, etc) - * and re-inits endpoint state (toggle etc) - * no response queued, just zero status == success. - * if we had more than one interface we couldn't - * use this "reset the config" shortcut. - */ - zero_reset_config(dev); - zero_set_config(dev, config); - value = 0; - } - spin_unlock(&dev->lock); - break; - case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) - goto unknown; - if (!dev->config) - break; - if (w_index != 0) { - value = -EDOM; - break; - } - *(u8 *)req->buf = 0; - value = min(w_length, (u16) 1); - break; - - /* - * These are the same vendor-specific requests supported by - * Intel's USB 2.0 compliance test devices. We exceed that - * device spec by allowing multiple-packet requests. - */ - case 0x5b: /* control WRITE test -- fill the buffer */ - if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) - goto unknown; - if (w_value || w_index) - break; - /* just read that many bytes into the buffer */ - if (w_length > USB_BUFSIZ) - break; - value = w_length; - break; - case 0x5c: /* control READ test -- return the buffer */ - if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) - goto unknown; - if (w_value || w_index) - break; - /* expect those bytes are still in the buffer; send back */ - if (w_length > USB_BUFSIZ - || w_length != req->length) - break; - value = w_length; - break; - - default: -unknown: - VDBG(dev, - "unknown control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - } - - /* respond with data transfer before status phase? */ - if (value >= 0) { - req->length = value; - req->zero = value < w_length; - value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - if (value < 0) { - DBG(dev, "ep_queue --> %d\n", value); - req->status = 0; - zero_setup_complete(gadget->ep0, req); - } - } - - /* device either stalls (value < 0) or reports success */ - return value; -} - -static void zero_disconnect(struct usb_gadget *gadget) -{ - struct zero_dev *dev = get_gadget_data(gadget); - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - zero_reset_config(dev); - - /* a more significant application might have some non-usb - * activities to quiesce here, saving resources like power - * or pushing the notification up a network stack. - */ - spin_unlock_irqrestore(&dev->lock, flags); - - /* next we may get setup() calls to enumerate new connections; - * or an unbind() during shutdown (including removing module). - */ -} - -static void zero_autoresume(unsigned long _dev) -{ - struct zero_dev *dev = (struct zero_dev *) _dev; - int status; - - /* normally the host would be woken up for something - * more significant than just a timer firing... - */ - if (dev->gadget->speed != USB_SPEED_UNKNOWN) { - status = usb_gadget_wakeup(dev->gadget); - DBG(dev, "wakeup --> %d\n", status); - } + disable_ep(cdev, in); + disable_ep(cdev, out); } /*-------------------------------------------------------------------------*/ -static void zero_unbind(struct usb_gadget *gadget) +static int __init zero_bind(struct usb_composite_dev *cdev) { - struct zero_dev *dev = get_gadget_data(gadget); - - DBG(dev, "unbind\n"); - - /* we've already been disconnected ... no i/o is active */ - if (dev->req) { - dev->req->length = USB_BUFSIZ; - free_ep_req(gadget->ep0, dev->req); - } - del_timer_sync(&dev->resume); - kfree(dev); - set_gadget_data(gadget, NULL); -} - -static int __init zero_bind(struct usb_gadget *gadget) -{ - struct zero_dev *dev; - struct usb_ep *ep; int gcnum; + struct usb_gadget *gadget = cdev->gadget; + int id; - /* FIXME this can't yet work right with SH ... it has only - * one configuration, numbered one. + /* Allocate string descriptor numbers ... note that string + * contents can be overridden by the composite_dev glue. */ - if (gadget_is_sh(gadget)) - return -ENODEV; - - /* Bulk-only drivers like this one SHOULD be able to - * autoconfigure on any sane usb controller driver, - * but there may also be important quirks to address. + id = usb_string_id(cdev); + if (id < 0) + return id; + strings_dev[STRING_MANUFACTURER_IDX].id = id; + device_desc.iManufacturer = id; + + id = usb_string_id(cdev); + if (id < 0) + return id; + strings_dev[STRING_PRODUCT_IDX].id = id; + device_desc.iProduct = id; + + id = usb_string_id(cdev); + if (id < 0) + return id; + strings_dev[STRING_SERIAL_IDX].id = id; + device_desc.iSerialNumber = id; + + /* Register primary, then secondary configuration. Note that + * SH3 only allows one config... */ - usb_ep_autoconfig_reset(gadget); - ep = usb_ep_autoconfig(gadget, &fs_source_desc); - if (!ep) { -autoconf_fail: - pr_err("%s: can't autoconfigure on %s\n", - shortname, gadget->name); - return -ENODEV; + if (loopdefault) { + loopback_add(cdev); + if (!gadget_is_sh(gadget)) + sourcesink_add(cdev); + } else { + sourcesink_add(cdev); + if (!gadget_is_sh(gadget)) + loopback_add(cdev); } - EP_IN_NAME = ep->name; - ep->driver_data = ep; /* claim */ - - ep = usb_ep_autoconfig(gadget, &fs_sink_desc); - if (!ep) - goto autoconf_fail; - EP_OUT_NAME = ep->name; - ep->driver_data = ep; /* claim */ gcnum = usb_gadget_controller_number(gadget); if (gcnum >= 0) @@ -1115,144 +241,44 @@ autoconf_fail: else { /* gadget zero is so simple (for now, no altsettings) that * it SHOULD NOT have problems with bulk-capable hardware. - * so warn about unrcognized controllers, don't panic. + * so just warn about unrcognized controllers -- don't panic. * * things like configuration and altsetting numbering * can need hardware-specific attention though. */ pr_warning("%s: controller '%s' not recognized\n", - shortname, gadget->name); + longname, gadget->name); device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); } - /* ok, we made sense of the hardware ... */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - spin_lock_init(&dev->lock); - dev->gadget = gadget; - set_gadget_data(gadget, dev); - - init_timer(&dev->resume); - dev->resume.function = zero_autoresume; - dev->resume.data = (unsigned long) dev; - - /* preallocate control response and buffer */ - dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); - if (!dev->req) - goto enomem; - dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); - if (!dev->req->buf) - goto enomem; - - dev->req->complete = zero_setup_complete; - - device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; - - if (gadget_is_dualspeed(gadget)) { - /* assume ep0 uses the same value for both speeds ... */ - dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; - - /* and that all endpoints are dual-speed */ - hs_source_desc.bEndpointAddress = - fs_source_desc.bEndpointAddress; - hs_sink_desc.bEndpointAddress = - fs_sink_desc.bEndpointAddress; - } - - if (gadget_is_otg(gadget)) { - otg_descriptor.bmAttributes |= USB_OTG_HNP, - source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - } - - usb_gadget_set_selfpowered(gadget); - - if (autoresume) { - source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - } - - gadget->ep0->driver_data = dev; - - INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname); - INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, - EP_OUT_NAME, EP_IN_NAME); + INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); return 0; - -enomem: - zero_unbind(gadget); - return -ENOMEM; } -/*-------------------------------------------------------------------------*/ - -static void zero_suspend(struct usb_gadget *gadget) -{ - struct zero_dev *dev = get_gadget_data(gadget); - - if (gadget->speed == USB_SPEED_UNKNOWN) - return; - - if (autoresume) { - mod_timer(&dev->resume, jiffies + (HZ * autoresume)); - DBG(dev, "suspend, wakeup in %d seconds\n", autoresume); - } else - DBG(dev, "suspend\n"); -} - -static void zero_resume(struct usb_gadget *gadget) -{ - struct zero_dev *dev = get_gadget_data(gadget); - - DBG(dev, "resume\n"); - del_timer(&dev->resume); -} - - -/*-------------------------------------------------------------------------*/ - -static struct usb_gadget_driver zero_driver = { -#ifdef CONFIG_USB_GADGET_DUALSPEED - .speed = USB_SPEED_HIGH, -#else - .speed = USB_SPEED_FULL, -#endif - .function = (char *) longname, +static struct usb_composite_driver zero_driver = { + .name = "zero", + .dev = &device_desc, + .strings = dev_strings, .bind = zero_bind, - .unbind = __exit_p(zero_unbind), - - .setup = zero_setup, - .disconnect = zero_disconnect, - - .suspend = zero_suspend, - .resume = zero_resume, - - .driver = { - .name = (char *) shortname, - .owner = THIS_MODULE, - }, }; MODULE_AUTHOR("David Brownell"); MODULE_LICENSE("GPL"); - static int __init init(void) { - return usb_gadget_register_driver(&zero_driver); + return usb_composite_register(&zero_driver); } module_init(init); static void __exit cleanup(void) { - usb_gadget_unregister_driver(&zero_driver); + usb_composite_unregister(&zero_driver); } module_exit(cleanup); - diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 08a4335401a9..bf69f4739107 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -19,263 +19,304 @@ #define USB_MCFG_RDCOMB (1<<30) #define USB_MCFG_SSDEN (1<<23) #define USB_MCFG_PHYPLLEN (1<<19) +#define USB_MCFG_UCECLKEN (1<<18) #define USB_MCFG_EHCCLKEN (1<<17) +#ifdef CONFIG_DMA_COHERENT #define USB_MCFG_UCAM (1<<7) +#else +#define USB_MCFG_UCAM (0) +#endif #define USB_MCFG_EBMEN (1<<3) #define USB_MCFG_EMEMEN (1<<2) -#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN) +#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN) +#define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \ + USBH_ENABLE_CE | USB_MCFG_SSDEN | \ + USB_MCFG_UCAM | USB_MCFG_EBMEN | \ + USB_MCFG_EMEMEN) -#ifdef CONFIG_DMA_COHERENT -#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ - | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ - | USB_MCFG_SSDEN | USB_MCFG_UCAM \ - | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) -#else -#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ - | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ - | USB_MCFG_SSDEN \ - | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) -#endif #define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN) extern int usb_disabled(void); -/*-------------------------------------------------------------------------*/ - -static void au1xxx_start_ehc(struct platform_device *dev) +static void au1xxx_start_ehc(void) { - pr_debug(__FILE__ ": starting Au1xxx EHCI USB Controller\n"); - - /* write HW defaults again in case Yamon cleared them */ - if (au_readl(USB_HOST_CONFIG) == 0) { - au_writel(0x00d02000, USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); - udelay(1000); - } - /* enable host controller */ - au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); - udelay(1000); - au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), - USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); + /* enable clock to EHCI block and HS PHY PLL*/ + au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG); + au_sync(); udelay(1000); - pr_debug(__FILE__ ": Clock to USB host has been enabled\n"); + /* enable EHCI mmio */ + au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); + au_sync(); + udelay(1000); } -static void au1xxx_stop_ehc(struct platform_device *dev) +static void au1xxx_stop_ehc(void) { - pr_debug(__FILE__ ": stopping Au1xxx EHCI USB Controller\n"); + unsigned long c; /* Disable mem */ - au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG); + au_sync(); udelay(1000); - /* Disable clock */ - au_writel(~USB_MCFG_EHCCLKEN & au_readl(USB_HOST_CONFIG), - USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); + + /* Disable EHC clock. If the HS PHY is unused disable it too. */ + c = au_readl(USB_HOST_CONFIG) & ~USB_MCFG_EHCCLKEN; + if (!(c & USB_MCFG_UCECLKEN)) /* UDC disabled? */ + c &= ~USB_MCFG_PHYPLLEN; /* yes: disable HS PHY PLL */ + au_writel(c, USB_HOST_CONFIG); + au_sync(); } -/*-------------------------------------------------------------------------*/ +static const struct hc_driver ehci_au1xxx_hc_driver = { + .description = hcd_name, + .product_desc = "Au1xxx EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + * + * FIXME -- ehci_init() doesn't do enough here. + * See ehci-ppc-soc for a complete implementation. + */ + .reset = ehci_init, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, -/** - * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - * - */ -int usb_ehci_au1xxx_probe(const struct hc_driver *driver, - struct usb_hcd **hcd_out, struct platform_device *dev) + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, +}; + +static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) { - int retval; struct usb_hcd *hcd; struct ehci_hcd *ehci; + int ret; -#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) + if (usb_disabled()) + return -ENODEV; +#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) /* Au1200 AB USB does not support coherent memory */ if (!(read_c0_prid() & 0xff)) { - pr_info("%s: this is chip revision AB!\n", dev->name); - pr_info("%s: update your board or re-configure the kernel\n", - dev->name); + printk(KERN_INFO "%s: this is chip revision AB!\n", pdev->name); + printk(KERN_INFO "%s: update your board or re-configure" + " the kernel\n", pdev->name); return -ENODEV; } #endif - au1xxx_start_ehc(dev); - - if (dev->resource[1].flags != IORESOURCE_IRQ) { + if (pdev->resource[1].flags != IORESOURCE_IRQ) { pr_debug("resource[1] is not IORESOURCE_IRQ"); - retval = -ENOMEM; + return -ENOMEM; } - hcd = usb_create_hcd(driver, &dev->dev, "Au1xxx"); + hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx"); if (!hcd) return -ENOMEM; - hcd->rsrc_start = dev->resource[0].start; - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; + + hcd->rsrc_start = pdev->resource[0].start; + hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed"); - retval = -EBUSY; + ret = -EBUSY; goto err1; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { pr_debug("ioremap failed"); - retval = -ENOMEM; + ret = -ENOMEM; goto err2; } + au1xxx_start_ehc(); + ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); - /* ehci_hcd_init(hcd_to_ehci(hcd)); */ - - retval = - usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED); - if (retval == 0) - return retval; + ret = usb_add_hcd(hcd, pdev->resource[1].start, + IRQF_DISABLED | IRQF_SHARED); + if (ret == 0) { + platform_set_drvdata(pdev, hcd); + return ret; + } - au1xxx_stop_ehc(dev); + au1xxx_stop_ehc(); iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); - return retval; + return ret; } -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -void usb_ehci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) +static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) { + struct usb_hcd *hcd = platform_get_drvdata(pdev); + usb_remove_hcd(hcd); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); - au1xxx_stop_ehc(dev); + au1xxx_stop_ehc(); + platform_set_drvdata(pdev, NULL); + + return 0; } -/*-------------------------------------------------------------------------*/ +#ifdef CONFIG_PM +static int ehci_hcd_au1xxx_drv_suspend(struct platform_device *pdev, + pm_message_t message) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + unsigned long flags; + int rc; -static const struct hc_driver ehci_au1xxx_hc_driver = { - .description = hcd_name, - .product_desc = "Au1xxx EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), + return 0; + rc = 0; - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, + if (time_before(jiffies, ehci->next_statechange)) + msleep(10); - /* - * basic lifecycle operations + /* Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. * - * FIXME -- ehci_init() doesn't do enough here. - * See ehci-ppc-soc for a complete implementation. - */ - .reset = ehci_init, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, + spin_lock_irqsave(&ehci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED) { + rc = -EINVAL; + goto bail; + } + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + (void)ehci_readl(ehci, &ehci->regs->intr_enable); - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, + /* make sure snapshot being resumed re-enumerates everything */ + if (message.event == PM_EVENT_PRETHAW) { + ehci_halt(ehci); + ehci_reset(ehci); + } - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, -}; + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); -/*-------------------------------------------------------------------------*/ + au1xxx_stop_ehc(); -static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd = NULL; - int ret; +bail: + spin_unlock_irqrestore(&ehci->lock, flags); - pr_debug("In ehci_hcd_au1xxx_drv_probe\n"); + // could save FLADJ in case of Vaux power loss + // ... we'd only use it to handle clock skew - if (usb_disabled()) - return -ENODEV; - - /* FIXME we only want one one probe() not two */ - ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev); - return ret; + return rc; } -static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) + +static int ehci_hcd_au1xxx_drv_resume(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); - /* FIXME we only want one one remove() not two */ - usb_ehci_au1xxx_remove(hcd, pdev); - return 0; -} + au1xxx_start_ehc(); - /*TBD*/ -/*static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct usb_hcd *hcd = dev_get_drvdata(dev); + // maybe restore FLADJ - return 0; -} -static int ehci_hcd_au1xxx_drv_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct usb_hcd *hcd = dev_get_drvdata(dev); + if (time_before(jiffies, ehci->next_statechange)) + msleep(100); + + /* Mark hardware accessible again as we are out of D3 state by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + /* If CF is still set, we maintained PCI Vaux power. + * Just undo the effect of ehci_pci_suspend(). + */ + if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { + int mask = INTR_MASK; + + if (!hcd->self.root_hub->do_remote_wakeup) + mask &= ~STS_PCD; + ehci_writel(ehci, mask, &ehci->regs->intr_enable); + ehci_readl(ehci, &ehci->regs->intr_enable); + return 0; + } + + ehci_dbg(ehci, "lost power, restarting\n"); + usb_root_hub_lost_power(hcd->self.root_hub); + + /* Else reset, to cope with power loss or flush-to-storage + * style "resume" having let BIOS kick in during reboot. + */ + (void) ehci_halt(ehci); + (void) ehci_reset(ehci); + + /* emptying the schedule aborts any urbs */ + spin_lock_irq(&ehci->lock); + if (ehci->reclaim) + end_unlink_async(ehci); + ehci_work(ehci); + spin_unlock_irq(&ehci->lock); + + ehci_writel(ehci, ehci->command, &ehci->regs->command); + ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); + ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + + /* here we "know" root ports should always stay powered */ + ehci_port_power(ehci, 1); + + hcd->state = HC_STATE_SUSPENDED; return 0; } -*/ -MODULE_ALIAS("platform:au1xxx-ehci"); + +#else +#define ehci_hcd_au1xxx_drv_suspend NULL +#define ehci_hcd_au1xxx_drv_resume NULL +#endif + static struct platform_driver ehci_hcd_au1xxx_driver = { - .probe = ehci_hcd_au1xxx_drv_probe, - .remove = ehci_hcd_au1xxx_drv_remove, - .shutdown = usb_hcd_platform_shutdown, - /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ - /*.resume = ehci_hcd_au1xxx_drv_resume, */ + .probe = ehci_hcd_au1xxx_drv_probe, + .remove = ehci_hcd_au1xxx_drv_remove, + .shutdown = usb_hcd_platform_shutdown, + .suspend = ehci_hcd_au1xxx_drv_suspend, + .resume = ehci_hcd_au1xxx_drv_resume, .driver = { - .name = "au1xxx-ehci", + .name = "au1xxx-ehci", + .owner = THIS_MODULE, } }; + +MODULE_ALIAS("platform:au1xxx-ehci"); diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 0f82fdcaef09..b0f8ed5a7fb9 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -676,7 +676,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) "%s\n" "SUSPENDED (no register access)\n", hcd->self.controller->bus->name, - hcd->self.controller->bus_id, + dev_name(hcd->self.controller), hcd->product_desc); goto done; } @@ -688,7 +688,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) "%s\n" "EHCI %x.%02x, hcd state %d\n", hcd->self.controller->bus->name, - hcd->self.controller->bus_id, + dev_name(hcd->self.controller), hcd->product_desc, i >> 8, i & 0x0ff, hcd->state); size -= temp; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 7370d6187c64..01c3da34f678 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -56,7 +56,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, - "No platform data for %s.\n", pdev->dev.bus_id); + "No platform data for %s.\n", dev_name(&pdev->dev)); return -ENODEV; } @@ -69,7 +69,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, (pdata->operating_mode == FSL_USB2_DR_OTG))) { dev_err(&pdev->dev, "Non Host Mode configured for %s. Wrong driver linked.\n", - pdev->dev.bus_id); + dev_name(&pdev->dev)); return -ENODEV; } @@ -77,12 +77,12 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, if (!res) { dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", - pdev->dev.bus_id); + dev_name(&pdev->dev)); return -ENODEV; } irq = res->start; - hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; goto err1; @@ -92,7 +92,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, if (!res) { dev_err(&pdev->dev, "Found HC with no register addr. Check %s setup!\n", - pdev->dev.bus_id); + dev_name(&pdev->dev)); retval = -ENODEV; goto err2; } @@ -132,7 +132,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, err2: usb_put_hcd(hcd); err1: - dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval); + dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); return retval; } @@ -230,8 +230,13 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) /* put controller in host mode. */ ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE); +#ifdef CONFIG_PPC_85xx + out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); + out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); +#else out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); +#endif out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); } diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 369a8a5ea7bb..d9d53f289caf 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -84,7 +84,7 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ -#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ +#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */ /* Initial IRQ latency: faster than hw default */ static int log2_irq_thresh = 0; // 0 to 6 diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index 9d042f220097..f9575c409124 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -77,12 +77,12 @@ static int ixp4xx_ehci_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", - pdev->dev.bus_id); + dev_name(&pdev->dev)); return -ENODEV; } irq = res->start; - hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; goto fail_create_hcd; @@ -92,7 +92,7 @@ static int ixp4xx_ehci_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "Found HC with no register addr. Check %s setup!\n", - pdev->dev.bus_id); + dev_name(&pdev->dev)); retval = -ENODEV; goto fail_request_resource; } @@ -126,7 +126,7 @@ fail_ioremap: fail_request_resource: usb_put_hcd(hcd); fail_create_hcd: - dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval); + dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); return retval; } diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index ab625f0ba1d9..5fbdc14e63b3 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -204,7 +204,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev) if (irq <= 0) { dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", - pdev->dev.bus_id); + dev_name(&pdev->dev)); err = -ENODEV; goto err1; } @@ -213,7 +213,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "Found HC with no register addr. Check %s setup!\n", - pdev->dev.bus_id); + dev_name(&pdev->dev)); err = -ENODEV; goto err1; } @@ -233,7 +233,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev) } hcd = usb_create_hcd(&ehci_orion_hc_driver, - &pdev->dev, pdev->dev.bus_id); + &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { err = -ENOMEM; goto err3; @@ -276,7 +276,7 @@ err2: release_mem_region(res->start, res->end - res->start + 1); err1: dev_err(&pdev->dev, "init %s fail, %d\n", - pdev->dev.bus_id, err); + dev_name(&pdev->dev), err); return err; } diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 37e6abeb794c..0eba894bcb01 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -128,7 +128,7 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev) dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ - hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id); + hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev_name(&dev->core)); if (!hcd) { dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index b85b54160cda..2622b6596d7c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1116,8 +1116,7 @@ static void scan_async (struct ehci_hcd *ehci) struct ehci_qh *qh; enum ehci_timer_action action = TIMER_IO_WATCHDOG; - if (!++(ehci->stamp)) - ehci->stamp++; + ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: qh = ehci->async->qh_next.qh; @@ -1142,18 +1141,20 @@ rescan: } } - /* unlink idle entries, reducing HC PCI usage as well + /* unlink idle entries, reducing DMA usage as well * as HCD schedule-scanning costs. delay for any qh * we just scanned, there's a not-unusual case that it * doesn't stay idle for long. * (plus, avoids some kind of re-activation race.) */ - if (list_empty (&qh->qtd_list)) { - if (qh->stamp == ehci->stamp) + if (list_empty(&qh->qtd_list) + && qh->qh_state == QH_STATE_LINKED) { + if (!ehci->reclaim + && ((ehci->stamp - qh->stamp) & 0x1fff) + >= (EHCI_SHRINK_FRAMES * 8)) + start_unlink_async(ehci, qh); + else action = TIMER_ASYNC_SHRINK; - else if (!ehci->reclaim - && qh->qh_state == QH_STATE_LINKED) - start_unlink_async (ehci, qh); } qh = qh->qh_next.qh; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 90245fd8bac4..5799298364fb 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -198,7 +198,10 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) break; // case TIMER_ASYNC_SHRINK: default: - t = EHCI_SHRINK_JIFFIES; + /* add a jiffie since we synch against the + * 8 KHz uframe counter. + */ + t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; break; } mod_timer(&ehci->watchdog, t + jiffies); diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 20b9a0d07420..31178e10cbbe 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -94,6 +94,10 @@ static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) u16 w; int quot = len % 4; + /* buffer is already in 'usb data order', which is LE. */ + /* When reading buffer as u16, we have to take care byte order */ + /* doesn't get mixed up */ + if ((unsigned long)dp2 & 1) { /* not aligned */ for (; len > 1; len -= 2) { @@ -105,8 +109,11 @@ static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) isp116x_write_data16(isp116x, (u16) * dp); } else { /* aligned */ - for (; len > 1; len -= 2) - isp116x_raw_write_data16(isp116x, *dp2++); + for (; len > 1; len -= 2) { + /* Keep byte order ! */ + isp116x_raw_write_data16(isp116x, cpu_to_le16(*dp2++)); + } + if (len) isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2)); } @@ -124,6 +131,10 @@ static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) u16 w; int quot = len % 4; + /* buffer is already in 'usb data order', which is LE. */ + /* When reading buffer as u16, we have to take care byte order */ + /* doesn't get mixed up */ + if ((unsigned long)dp2 & 1) { /* not aligned */ for (; len > 1; len -= 2) { @@ -131,12 +142,16 @@ static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) *dp++ = w & 0xff; *dp++ = (w >> 8) & 0xff; } + if (len) *dp = 0xff & isp116x_read_data16(isp116x); } else { /* aligned */ - for (; len > 1; len -= 2) - *dp2++ = isp116x_raw_read_data16(isp116x); + for (; len > 1; len -= 2) { + /* Keep byte order! */ + *dp2++ = le16_to_cpu(isp116x_raw_read_data16(isp116x)); + } + if (len) *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x); } @@ -1592,7 +1607,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev) } /* allocate and initialize hcd */ - hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { ret = -ENOMEM; goto err5; diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 65aa5ecf569a..c858f2adb929 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -38,6 +38,7 @@ struct isp1760_hcd { unsigned i_thresh; unsigned long reset_done; unsigned long next_statechange; + unsigned int devflags; }; static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) @@ -378,9 +379,31 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); int result; - u32 scratch; + u32 scratch, hwmode; + + /* Setup HW Mode Control: This assumes a level active-low interrupt */ + hwmode = HW_DATA_BUS_32BIT; + + if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) + hwmode &= ~HW_DATA_BUS_32BIT; + if (priv->devflags & ISP1760_FLAG_ANALOG_OC) + hwmode |= HW_ANA_DIGI_OC; + if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH) + hwmode |= HW_DACK_POL_HIGH; + if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH) + hwmode |= HW_DREQ_POL_HIGH; + + /* + * We have to set this first in case we're in 16-bit mode. + * Write it twice to ensure correct upper bits if switching + * to 16-bit mode. + */ + isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL); + isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL); isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG); + /* Change bus pattern */ + scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG); scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG); if (scratch != 0xdeadbabe) { printk(KERN_ERR "ISP1760: Scratch test failed.\n"); @@ -403,17 +426,29 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) /* Step 11 passed */ - isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG); - isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE); + isp1760_info(priv, "bus width: %d, oc: %s\n", + (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ? + 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ? + "analog" : "digital"); /* ATL reset */ - scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); - isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL); + isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL); mdelay(10); - isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL); + isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL); - isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL); - mdelay(10); + isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG); + isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE); + + /* + * PORT 1 Control register of the ISP1760 is the OTG control + * register on ISP1761. + */ + if (!(priv->devflags & ISP1760_FLAG_ISP1761) && + !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) { + isp1760_writel(PORT1_POWER | PORT1_INIT2, + hcd->regs + HC_PORT1_CTRL); + mdelay(10); + } priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS); @@ -453,8 +488,7 @@ static int isp1760_run(struct usb_hcd *hcd) hcd->state = HC_STATE_RUNNING; isp1760_enable_interrupts(hcd); temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); - temp |= FINAL_HW_CONFIG; - isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL); + isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL); command = isp1760_readl(hcd->regs + HC_USBCMD); command &= ~(CMD_LRESET|CMD_RESET); @@ -782,8 +816,8 @@ static void enqueue_one_int_qtd(u32 int_regs, u32 payload, qtd->status |= slot << 16; } -void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, - struct isp1760_qtd *qtd) +static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, + struct isp1760_qtd *qtd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); u32 skip_map, or_map; @@ -816,8 +850,8 @@ void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG); } -void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, - struct isp1760_qtd *qtd) +static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, + struct isp1760_qtd *qtd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); u32 skip_map, or_map; @@ -1592,7 +1626,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, struct inter_packet_info *ints; u32 i; u32 reg_base, or_reg, skip_reg; - int flags; + unsigned long flags; struct ptd ptd; switch (usb_pipetype(urb->pipe)) { @@ -2061,7 +2095,7 @@ static void isp1760_endpoint_disable(struct usb_hcd *usb_hcd, struct isp1760_hcd *priv = hcd_to_priv(usb_hcd); struct isp1760_qh *qh; struct isp1760_qtd *qtd; - u32 flags; + unsigned long flags; spin_lock_irqsave(&priv->lock, flags); qh = ep->hcpriv; @@ -2112,6 +2146,7 @@ static int isp1760_get_frame(struct usb_hcd *hcd) static void isp1760_stop(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 temp; isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, NULL, 0); @@ -2120,7 +2155,8 @@ static void isp1760_stop(struct usb_hcd *hcd) spin_lock_irq(&priv->lock); ehci_reset(priv); /* Disable IRQ */ - isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL); + temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); + isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL); spin_unlock_irq(&priv->lock); isp1760_writel(0, hcd->regs + HC_CONFIGFLAG); @@ -2128,10 +2164,11 @@ static void isp1760_stop(struct usb_hcd *hcd) static void isp1760_shutdown(struct usb_hcd *hcd) { - u32 command; + u32 command, temp; isp1760_stop(hcd); - isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL); + temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); + isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL); command = isp1760_readl(hcd->regs + HC_USBCMD); command &= ~CMD_RUN; @@ -2183,7 +2220,8 @@ void deinit_kmem_cache(void) } struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname) + u64 irqflags, struct device *dev, const char *busname, + unsigned int devflags) { struct usb_hcd *hcd; struct isp1760_hcd *priv; @@ -2195,11 +2233,12 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, /* prevent usb-core allocating DMA pages */ dev->dma_mask = NULL; - hcd = usb_create_hcd(&isp1760_hc_driver, dev, dev->bus_id); + hcd = usb_create_hcd(&isp1760_hc_driver, dev, dev_name(dev)); if (!hcd) return ERR_PTR(-ENOMEM); priv = hcd_to_priv(hcd); + priv->devflags = devflags; init_memory(priv); hcd->regs = ioremap(res_start, res_len); if (!hcd->regs) { diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 3d86d0f6b147..6473dd86993c 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -3,7 +3,8 @@ /* exports for if */ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname); + u64 irqflags, struct device *dev, const char *busname, + unsigned int devflags); int init_kmem_once(void); void deinit_kmem_cache(void); @@ -31,6 +32,7 @@ void deinit_kmem_cache(void); /* Configuration Register */ #define HC_HW_MODE_CTRL 0x300 #define ALL_ATX_RESET (1 << 31) +#define HW_ANA_DIGI_OC (1 << 15) #define HW_DATA_BUS_32BIT (1 << 8) #define HW_DACK_POL_HIGH (1 << 6) #define HW_DREQ_POL_HIGH (1 << 5) @@ -56,13 +58,14 @@ void deinit_kmem_cache(void); #define PORT1_POWER (3 << 3) #define PORT1_INIT1 (1 << 7) #define PORT1_INIT2 (1 << 23) +#define HW_OTG_CTRL_SET 0x374 +#define HW_OTG_CTRL_CLR 0x376 /* Interrupt Register */ #define HC_INTERRUPT_REG 0x310 #define HC_INTERRUPT_ENABLE 0x314 #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) -#define FINAL_HW_CONFIG (HW_GLOBAL_INTR_EN | HW_DATA_BUS_32BIT) #define HC_ISO_INT (1 << 9) #define HC_ATL_INT (1 << 8) @@ -122,6 +125,19 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, #define isp1760_err(priv, fmt, args...) \ dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args) +/* + * Device flags that can vary from board to board. All of these + * indicate the most "atypical" case, so that a devflags of 0 is + * a sane default configuration. + */ +#define ISP1760_FLAG_PORT1_DIS 0x00000001 /* Port 1 disabled */ +#define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ +#define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ +#define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ +#define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */ +#define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */ +#define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ + /* chip memory management */ struct memory_chunk { unsigned int start; diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index c9db3fe98726..051ef7b6bdc6 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -35,13 +35,15 @@ static int of_isp1760_probe(struct of_device *dev, int virq; u64 res_len; int ret; + const unsigned int *prop; + unsigned int devflags = 0; ret = of_address_to_resource(dp, 0, &memory); if (ret) return -ENXIO; res = request_mem_region(memory.start, memory.end - memory.start + 1, - dev->dev.bus_id); + dev_name(&dev->dev)); if (!res) return -EBUSY; @@ -55,8 +57,32 @@ static int of_isp1760_probe(struct of_device *dev, virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); + if (of_device_is_compatible(dp, "nxp,usb-isp1761")) + devflags |= ISP1760_FLAG_ISP1761; + + if (of_get_property(dp, "port1-disable", NULL) != NULL) + devflags |= ISP1760_FLAG_PORT1_DIS; + + /* Some systems wire up only 16 of the 32 data lines */ + prop = of_get_property(dp, "bus-width", NULL); + if (prop && *prop == 16) + devflags |= ISP1760_FLAG_BUS_WIDTH_16; + + if (of_get_property(dp, "port1-otg", NULL) != NULL) + devflags |= ISP1760_FLAG_OTG_EN; + + if (of_get_property(dp, "analog-oc", NULL) != NULL) + devflags |= ISP1760_FLAG_ANALOG_OC; + + if (of_get_property(dp, "dack-polarity", NULL) != NULL) + devflags |= ISP1760_FLAG_DACK_POL_HIGH; + + if (of_get_property(dp, "dreq-polarity", NULL) != NULL) + devflags |= ISP1760_FLAG_DREQ_POL_HIGH; + hcd = isp1760_register(memory.start, res_len, virq, - IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id); + IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), + devflags); if (IS_ERR(hcd)) { ret = PTR_ERR(hcd); goto release_reg; @@ -87,6 +113,9 @@ static struct of_device_id of_isp1760_match[] = { { .compatible = "nxp,usb-isp1760", }, + { + .compatible = "nxp,usb-isp1761", + }, { }, }; MODULE_DEVICE_TABLE(of, of_isp1760_match); @@ -116,6 +145,7 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, int length; int status = 1; struct usb_hcd *hcd; + unsigned int devflags = 0; if (usb_disabled()) return -ENODEV; @@ -200,7 +230,8 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, dev->dev.dma_mask = NULL; hcd = isp1760_register(pci_mem_phy0, length, dev->irq, - IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id); + IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), + devflags); pci_set_drvdata(dev, hcd); if (!hcd) return 0; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index e534f9de0f05..a5d8e550d897 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -91,7 +91,7 @@ static void at91_stop_hc(struct platform_device *pdev) /*-------------------------------------------------------------------------*/ -static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); +static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -184,13 +184,14 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, * context, "rmmod" or something similar. * */ -static int usb_hcd_at91_remove(struct usb_hcd *hcd, +static void usb_hcd_at91_remove(struct usb_hcd *hcd, struct platform_device *pdev) { usb_remove_hcd(hcd); at91_stop_hc(pdev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); if (cpu_is_at91sam9261()) clk_put(hclk); @@ -199,7 +200,6 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd, fclk = iclk = hclk = NULL; dev_set_drvdata(&pdev->dev, NULL); - return 0; } /*-------------------------------------------------------------------------*/ @@ -309,7 +309,8 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) } device_init_wakeup(&pdev->dev, 0); - return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); + usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); + return 0; } #ifdef CONFIG_PM diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 68c17f5ea8ea..c0948008fe3d 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -34,7 +34,8 @@ #ifdef __LITTLE_ENDIAN #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C) #elif __BIG_ENDIAN -#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | USBH_ENABLE_BE) +#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | \ + USBH_ENABLE_BE) #else #error not byte order defined #endif @@ -46,213 +47,87 @@ #define USB_MCFG_RDCOMB (1<<30) #define USB_MCFG_SSDEN (1<<23) #define USB_MCFG_OHCCLKEN (1<<16) +#ifdef CONFIG_DMA_COHERENT #define USB_MCFG_UCAM (1<<7) +#else +#define USB_MCFG_UCAM (0) +#endif #define USB_MCFG_OBMEN (1<<1) #define USB_MCFG_OMEMEN (1<<0) #define USBH_ENABLE_CE USB_MCFG_OHCCLKEN -#ifdef CONFIG_DMA_COHERENT -#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ - | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ - | USB_MCFG_SSDEN | USB_MCFG_UCAM \ - | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) -#else -#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ - | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ - | USB_MCFG_SSDEN \ - | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) -#endif + +#define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \ + USBH_ENABLE_CE | USB_MCFG_SSDEN | \ + USB_MCFG_UCAM | \ + USB_MCFG_OBMEN | USB_MCFG_OMEMEN) + #define USBH_DISABLE (USB_MCFG_OBMEN | USB_MCFG_OMEMEN) #endif /* Au1200 */ extern int usb_disabled(void); -/*-------------------------------------------------------------------------*/ - -static void au1xxx_start_ohc(struct platform_device *dev) +static void au1xxx_start_ohc(void) { - printk(KERN_DEBUG __FILE__ - ": starting Au1xxx OHCI USB Controller\n"); - /* enable host controller */ - #ifndef CONFIG_SOC_AU1200 - au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); + au_sync(); udelay(1000); - au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG); - udelay(1000); - -#else /* Au1200 */ - /* write HW defaults again in case Yamon cleared them */ - if (au_readl(USB_HOST_CONFIG) == 0) { - au_writel(0x00d02000, USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); - udelay(1000); - } - au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); + au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); + au_sync(); udelay(1000); - au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); - udelay(1000); - -#endif /* Au1200 */ -#ifndef CONFIG_SOC_AU1200 /* wait for reset complete (read register twice; see au1500 errata) */ while (au_readl(USB_HOST_CONFIG), !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) -#endif udelay(1000); - printk(KERN_DEBUG __FILE__ - ": Clock to USB host has been enabled \n"); -} - -static void au1xxx_stop_ohc(struct platform_device *dev) -{ - printk(KERN_DEBUG __FILE__ - ": stopping Au1xxx OHCI USB Controller\n"); - -#ifndef CONFIG_SOC_AU1200 - - /* Disable clock */ - au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); - #else /* Au1200 */ - - /* Disable mem */ - au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG); + au_sync(); udelay(1000); - /* Disable clock */ - au_writel(~USBH_ENABLE_CE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); - au_readl(USB_HOST_CONFIG); + + au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); + au_sync(); + udelay(2000); #endif /* Au1200 */ } - -/*-------------------------------------------------------------------------*/ - -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - - -/** - * usb_ohci_au1xxx_probe - initialize Au1xxx-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - * - */ -static int usb_ohci_au1xxx_probe(const struct hc_driver *driver, - struct platform_device *dev) +static void au1xxx_stop_ohc(void) { - int retval; - struct usb_hcd *hcd; - -#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) - /* Au1200 AB USB does not support coherent memory */ - if (!(read_c0_prid() & 0xff)) { - pr_info("%s: this is chip revision AB !!\n", - dev->name); - pr_info("%s: update your board or re-configure the kernel\n", - dev->name); - return -ENODEV; - } +#ifdef CONFIG_SOC_AU1200 + /* Disable mem */ + au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG); + au_sync(); + udelay(1000); #endif - - if (dev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug("resource[1] is not IORESOURCE_IRQ\n"); - return -ENOMEM; - } - - hcd = usb_create_hcd(driver, &dev->dev, "au1xxx"); - if (!hcd) - return -ENOMEM; - hcd->rsrc_start = dev->resource[0].start; - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed\n"); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("ioremap failed\n"); - retval = -ENOMEM; - goto err2; - } - - au1xxx_start_ohc(dev); - ohci_hcd_init(hcd_to_ohci(hcd)); - - retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED); - if (retval == 0) - return retval; - - au1xxx_stop_ohc(dev); - iounmap(hcd->regs); - err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - err1: - usb_put_hcd(hcd); - return retval; -} - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_au1xxx_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -static void usb_ohci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) -{ - usb_remove_hcd(hcd); - au1xxx_stop_ohc(dev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); + /* Disable clock */ + au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); + au_sync(); } -/*-------------------------------------------------------------------------*/ - -static int __devinit -ohci_au1xxx_start (struct usb_hcd *hcd) +static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; - ohci_dbg (ohci, "ohci_au1xxx_start, ohci:%p", ohci); + ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci); - if ((ret = ohci_init (ohci)) < 0) + if ((ret = ohci_init(ohci)) < 0) return ret; - if ((ret = ohci_run (ohci)) < 0) { + if ((ret = ohci_run(ohci)) < 0) { err ("can't start %s", hcd->self.bus_name); - ohci_stop (hcd); + ohci_stop(hcd); return ret; } return 0; } -/*-------------------------------------------------------------------------*/ - static const struct hc_driver ohci_au1xxx_hc_driver = { .description = hcd_name, .product_desc = "Au1xxx OHCI", @@ -296,18 +171,66 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { .start_port_reset = ohci_start_port_reset, }; -/*-------------------------------------------------------------------------*/ - static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) { int ret; - - pr_debug ("In ohci_hcd_au1xxx_drv_probe"); + struct usb_hcd *hcd; if (usb_disabled()) return -ENODEV; - ret = usb_ohci_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev); +#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) + /* Au1200 AB USB does not support coherent memory */ + if (!(read_c0_prid() & 0xff)) { + printk(KERN_INFO "%s: this is chip revision AB !!\n", + pdev->name); + printk(KERN_INFO "%s: update your board or re-configure " + "the kernel\n", pdev->name); + return -ENODEV; + } +#endif + + if (pdev->resource[1].flags != IORESOURCE_IRQ) { + pr_debug("resource[1] is not IORESOURCE_IRQ\n"); + return -ENOMEM; + } + + hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx"); + if (!hcd) + return -ENOMEM; + + hcd->rsrc_start = pdev->resource[0].start; + hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + pr_debug("request_mem_region failed\n"); + ret = -EBUSY; + goto err1; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + pr_debug("ioremap failed\n"); + ret = -ENOMEM; + goto err2; + } + + au1xxx_start_ohc(); + ohci_hcd_init(hcd_to_ohci(hcd)); + + ret = usb_add_hcd(hcd, pdev->resource[1].start, + IRQF_DISABLED | IRQF_SHARED); + if (ret == 0) { + platform_set_drvdata(pdev, hcd); + return ret; + } + + au1xxx_stop_ohc(); + iounmap(hcd->regs); +err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err1: + usb_put_hcd(hcd); return ret; } @@ -315,30 +238,78 @@ static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - usb_ohci_au1xxx_remove(hcd, pdev); + usb_remove_hcd(hcd); + au1xxx_stop_ohc(); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + platform_set_drvdata(pdev, NULL); + return 0; } - /*TBD*/ -/*static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *dev) + +#ifdef CONFIG_PM +static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *pdev, + pm_message_t message) { - struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + unsigned long flags; + int rc; + + rc = 0; + + /* Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + * + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. + */ + spin_lock_irqsave(&ohci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED) { + rc = -EINVAL; + goto bail; + } + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + (void)ohci_readl(ohci, &ohci->regs->intrdisable); - return 0; + /* make sure snapshot being resumed re-enumerates everything */ + if (message.event == PM_EVENT_PRETHAW) + ohci_usb_reset(ohci); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + au1xxx_stop_ohc(); +bail: + spin_unlock_irqrestore(&ohci->lock, flags); + + return rc; } -static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev) + +static int ohci_hcd_au1xxx_drv_resume(struct platform_device *pdev) { - struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + au1xxx_start_ohc(); + + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + ohci_finish_controller_resume(hcd); return 0; } -*/ +#else +#define ohci_hcd_au1xxx_drv_suspend NULL +#define ohci_hcd_au1xxx_drv_resume NULL +#endif static struct platform_driver ohci_hcd_au1xxx_driver = { .probe = ohci_hcd_au1xxx_drv_probe, .remove = ohci_hcd_au1xxx_drv_remove, .shutdown = usb_hcd_platform_shutdown, - /*.suspend = ohci_hcd_au1xxx_drv_suspend, */ - /*.resume = ohci_hcd_au1xxx_drv_resume, */ + .suspend = ohci_hcd_au1xxx_drv_suspend, + .resume = ohci_hcd_au1xxx_drv_resume, .driver = { .name = "au1xxx-ohci", .owner = THIS_MODULE, diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index e06bfaebec54..7cef1d2f7ccc 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -651,7 +651,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) "%s\n" "%s version " DRIVER_VERSION "\n", hcd->self.controller->bus->name, - hcd->self.controller->bus_id, + dev_name(hcd->self.controller), hcd->product_desc, hcd_name); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index a8160d65f32b..26bc47941d01 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -974,7 +974,7 @@ MODULE_LICENSE ("GPL"); #define PCI_DRIVER ohci_pci_driver #endif -#ifdef CONFIG_SA1111 +#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111) #include "ohci-sa1111.c" #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index a19a4f80a6e1..6e5e5f81ac90 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -329,7 +329,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, } - hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; goto err0; diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 28b458f20cc3..6ad8f2fc57b9 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -109,8 +109,6 @@ static struct clk *usb_clk; static int isp1301_probe(struct i2c_adapter *adap); static int isp1301_detach(struct i2c_client *client); -static int isp1301_command(struct i2c_client *client, unsigned int cmd, - void *arg); static const unsigned short normal_i2c[] = { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; @@ -123,30 +121,37 @@ static struct i2c_client_address_data addr_data = { }; struct i2c_driver isp1301_driver = { - .class = I2C_CLASS_HWMON, + .driver = { + .name = "isp1301_pnx", + }, .attach_adapter = isp1301_probe, .detach_client = isp1301_detach, - .command = isp1301_command }; static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind) { struct i2c_client *c; + int err; c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) return -ENOMEM; - strcpy(c->name, "isp1301"); + strlcpy(c->name, "isp1301_pnx", I2C_NAME_SIZE); c->flags = 0; c->addr = addr; c->adapter = adap; c->driver = &isp1301_driver; + err = i2c_attach_client(c); + if (err) { + kfree(c); + return err; + } + isp1301_i2c_client = c; - return i2c_attach_client(c); + return 0; } static int isp1301_probe(struct i2c_adapter *adap) @@ -161,13 +166,6 @@ static int isp1301_detach(struct i2c_client *client) return 0; } -/* No commands defined */ -static int isp1301_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - return 0; -} - static void i2c_write(u8 buf, u8 subaddr) { char tmpbuf[2]; @@ -389,7 +387,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) != USB_CLOCK_MASK) ; - hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { err("Failed to allocate HC buffer"); ret = -ENOMEM; diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index a67252791223..91e6e101a4cc 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -14,8 +14,8 @@ */ #include <linux/signal.h> +#include <linux/of_platform.h> -#include <asm/of_platform.h> #include <asm/prom.h> diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index c1935ae537f8..55c95647f008 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -129,7 +129,7 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev) dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ - hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id); + hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev_name(&dev->core)); if (!hcd) { dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 9b547407c934..6a9b4c557953 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -159,9 +159,6 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) { int branch; - if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING) - return -EAGAIN; - ed->state = ED_OPER; ed->ed_prev = NULL; ed->ed_next = NULL; diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index e610698c6b60..21b164e4abeb 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -143,7 +143,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) goto err2; } - hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; goto err2; diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index 7275186db315..3660c83d80af 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -113,7 +113,7 @@ static int ssb_ohci_attach(struct ssb_device *dev) ssb_device_enable(dev, flags); hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, - dev->dev->bus_id); + dev_name(dev->dev)); if (!hcd) goto err_dev_disable; ohcidev = hcd_to_ssb_ohci(hcd); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 16667342b3c3..d5f02dddb120 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -312,9 +312,9 @@ static void put_child_connect_map(struct r8a66597 *r8a66597, int address) static void set_pipe_reg_addr(struct r8a66597_pipe *pipe, u8 dma_ch) { u16 pipenum = pipe->info.pipenum; - unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO}; - unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL}; - unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR}; + const unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO}; + const unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL}; + const unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR}; if (dma_ch > R8A66597_PIPE_NO_DMA) /* dma fifo not use? */ dma_ch = R8A66597_PIPE_NO_DMA; @@ -863,6 +863,32 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597, dev->dma_map = 0; } +static u16 get_interval(struct urb *urb, __u8 interval) +{ + u16 time = 1; + int i; + + if (urb->dev->speed == USB_SPEED_HIGH) { + if (interval > IITV) + time = IITV; + else + time = interval ? interval - 1 : 0; + } else { + if (interval > 128) { + time = IITV; + } else { + /* calculate the nearest value for PIPEPERI */ + for (i = 0; i < 7; i++) { + if ((1 << i) < interval && + (1 << (i + 1) > interval)) + time = 1 << i; + } + } + } + + return time; +} + static unsigned long get_timer_interval(struct urb *urb, __u8 interval) { __u8 i; @@ -901,10 +927,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.interval = 0; info.timer_interval = 0; } else { - if (ep->bInterval > IITV) - info.interval = IITV; - else - info.interval = ep->bInterval ? ep->bInterval - 1 : 0; + info.interval = get_interval(urb, ep->bInterval); info.timer_interval = get_timer_interval(urb, ep->bInterval); } if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) @@ -2244,6 +2267,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) struct r8a66597 *r8a66597; int ret = 0; int i; + unsigned long irq_trigger; if (pdev->dev.dma_mask) { ret = -EINVAL; @@ -2302,7 +2326,11 @@ static int __init r8a66597_probe(struct platform_device *pdev) INIT_LIST_HEAD(&r8a66597->child_device); hcd->rsrc_start = res->start; - ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); + if (irq_sense == INTL) + irq_trigger = IRQF_TRIGGER_LOW; + else + irq_trigger = IRQF_TRIGGER_FALLING; + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger); if (ret != 0) { err("Failed to add hcd"); goto clean_up; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 426575247b23..340d72da554a 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1674,7 +1674,7 @@ sl811h_probe(struct platform_device *dev) } /* allocate and initialize hcd */ - hcd = usb_create_hcd(&sl811h_hc_driver, &dev->dev, dev->dev.bus_id); + hcd = usb_create_hcd(&sl811h_hc_driver, &dev->dev, dev_name(&dev->dev)); if (!hcd) { retval = -ENOMEM; goto err5; diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 9b6323f768b2..20ad3c48fcb2 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3124,7 +3124,7 @@ static int __devinit u132_probe(struct platform_device *pdev) if (pdev->dev.dma_mask) return -EINVAL; - hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { printk(KERN_ERR "failed to create the usb hcd struct for U132\n" ); diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 8e4427aebb14..885b585360b9 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -12,7 +12,7 @@ * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu */ -static __u8 root_hub_hub_des[] = +static const __u8 root_hub_hub_des[] = { 0x09, /* __u8 bLength; */ 0x29, /* __u8 bDescriptorType; Hub-descriptor */ diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 093938697426..d2f61d5510e7 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -1421,7 +1421,8 @@ ofail: mutex_unlock(&cp->mutex); /* IOCTL functions */ -static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long auerchar_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { pauerchar_t ccp = (pauerchar_t) file->private_data; int ret = 0; @@ -1452,7 +1453,7 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int mutex_unlock(&ccp->mutex); return -ENODEV; } - + lock_kernel(); switch (cmd) { /* return != 0 if Transmitt channel ready to send */ @@ -1547,9 +1548,10 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int default: dbg ("IOCTL_AU_UNKNOWN"); - ret = -ENOIOCTLCMD; + ret = -ENOTTY; break; } + unlock_kernel(); /* release the mutexes */ mutex_unlock(&cp->mutex); mutex_unlock(&ccp->mutex); @@ -1860,7 +1862,7 @@ static const struct file_operations auerswald_fops = .llseek = no_llseek, .read = auerchar_read, .write = auerchar_write, - .ioctl = auerchar_ioctl, + .unlocked_ioctl = auerchar_ioctl, .open = auerchar_open, .release = auerchar_release, }; diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 20886c21e739..5d859ded5bbf 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -6,8 +6,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, as published by * the Free Software Foundation, version 2. - * - * $Id: emi62.c,v 1.15 2002/04/23 06:13:59 tapio Exp $ */ #include <linux/kernel.h> #include <linux/errno.h> diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index ec88b3bfee46..97c280971532 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -656,29 +656,6 @@ static int ftdi_elan_release(struct inode *inode, struct file *file) } -#define FTDI_ELAN_IOC_MAGIC 0xA1 -#define FTDI_ELAN_IOCDEBUG _IOC(_IOC_WRITE, FTDI_ELAN_IOC_MAGIC, 1, 132) -static int ftdi_elan_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case FTDI_ELAN_IOCDEBUG:{ - char line[132]; - int size = strncpy_from_user(line, - (const char __user *)arg, sizeof(line)); - if (size < 0) { - return -EINVAL; - } else { - printk(KERN_ERR "TODO: ioctl %s\n", line); - return 0; - } - } - default: - return -EFAULT; - } -} - - /* * * blocking bulk reads are used to get data from the device @@ -1222,7 +1199,6 @@ error_1: static const struct file_operations ftdi_elan_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = ftdi_elan_ioctl, .read = ftdi_elan_read, .write = ftdi_elan_write, .open = ftdi_elan_open, diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 1cb54a28347f..e6ca9979e3ae 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -474,8 +474,8 @@ exit: /** * iowarrior_ioctl */ -static int iowarrior_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long iowarrior_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct iowarrior *dev = NULL; __u8 *buffer; @@ -493,6 +493,7 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file, return -ENOMEM; /* lock this object */ + lock_kernel(); mutex_lock(&dev->mutex); /* verify that the device wasn't unplugged */ @@ -584,6 +585,7 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file, error_out: /* unlock the device */ mutex_unlock(&dev->mutex); + unlock_kernel(); kfree(buffer); return retval; } @@ -719,7 +721,7 @@ static const struct file_operations iowarrior_fops = { .owner = THIS_MODULE, .write = iowarrior_write, .read = iowarrior_read, - .ioctl = iowarrior_ioctl, + .unlocked_ioctl = iowarrior_ioctl, .open = iowarrior_open, .release = iowarrior_release, .poll = iowarrior_poll, diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 330c18e390b8..248a12aacef6 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -104,9 +104,7 @@ static int close_rio(struct inode *inode, struct file *file) return 0; } -static int -ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) { struct RioCommand rio_cmd; struct rio_usb_data *rio = &rio_instance; @@ -116,6 +114,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, int retries; int retval=0; + lock_kernel(); mutex_lock(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if (rio->present == 0 || rio->rio_dev == NULL) { @@ -254,6 +253,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, err_out: mutex_unlock(&(rio->lock)); + unlock_kernel(); return retval; } @@ -433,7 +433,7 @@ file_operations usb_rio_fops = { .owner = THIS_MODULE, .read = read_rio, .write = write_rio, - .ioctl = ioctl_rio, + .unlocked_ioctl = ioctl_rio, .open = open_rio, .release = close_rio, }; diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 33182f4c2267..fbace41a7cba 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -2982,9 +2982,8 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, return retval; } -static int -sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long +sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sisusb_usb_data *sisusb; struct sisusb_info x; @@ -2995,6 +2994,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; + lock_kernel(); mutex_lock(&sisusb->lock); /* Sanity check */ @@ -3053,6 +3053,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, err_out: mutex_unlock(&sisusb->lock); + unlock_kernel(); return retval; } @@ -3066,9 +3067,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) case SISUSB_GET_CONFIG_SIZE: case SISUSB_GET_CONFIG: case SISUSB_COMMAND: - lock_kernel(); - retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg); - unlock_kernel(); + retval = sisusb_ioctl(f, cmd, arg); return retval; default: @@ -3087,7 +3086,7 @@ static const struct file_operations usb_sisusb_fops = { #ifdef SISUSB_NEW_CONFIG_COMPAT .compat_ioctl = sisusb_compat_ioctl, #endif - .ioctl = sisusb_ioctl + .unlocked_ioctl = sisusb_ioctl }; static struct usb_class_driver usb_sisusb_class = { diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 7f7021ee4189..2db4228fbb01 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -146,7 +146,7 @@ static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, l return retval; } -static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct usb_lcd *dev; u16 bcdDevice; @@ -158,12 +158,14 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u switch (cmd) { case IOCTL_GET_HARD_VERSION: + lock_kernel(); bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice); sprintf(buf,"%1d%1d.%1d%1d", (bcdDevice & 0xF000)>>12, (bcdDevice & 0xF00)>>8, (bcdDevice & 0xF0)>>4, (bcdDevice & 0xF)); + unlock_kernel(); if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0) return -EFAULT; break; @@ -272,7 +274,7 @@ static const struct file_operations lcd_fops = { .read = lcd_read, .write = lcd_write, .open = lcd_open, - .ioctl = lcd_ioctl, + .unlocked_ioctl = lcd_ioctl, .release = lcd_release, }; diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 293a46247c3b..6566fc0a3228 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1162,8 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus) if (minor >= MON_BIN_MAX_MINOR) return 0; - dev = device_create(mon_bin_class, ubus? ubus->controller: NULL, - MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor); + dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL, + MKDEV(MAJOR(mon_bin_dev0), minor), NULL, + "usbmon%d", minor); if (IS_ERR(dev)) return 0; diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c index c7a595cd648a..ac8b0d5ce7f8 100644 --- a/drivers/usb/mon/mon_stat.c +++ b/drivers/usb/mon/mon_stat.c @@ -9,6 +9,7 @@ #include <linux/kernel.h> #include <linux/usb.h> +#include <linux/fs.h> #include <asm/uaccess.h> #include "usb_mon.h" @@ -42,19 +43,8 @@ static ssize_t mon_stat_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct snap *sp = file->private_data; - loff_t pos = *ppos; - int cnt; - if (pos < 0 || pos >= sp->slen) - return 0; - if (nbytes == 0) - return 0; - if ((cnt = sp->slen - pos) > nbytes) - cnt = nbytes; - if (copy_to_user(buf, sp->str + pos, cnt)) - return -EFAULT; - *ppos = pos + cnt; - return cnt; + return simple_read_from_buffer(buf, nbytes, ppos, sp->str, sp->slen); } static int mon_stat_release(struct inode *inode, struct file *file) diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 9a7681b55266..8878c1767fc8 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -64,14 +64,6 @@ config USB_SERIAL_AIRCABLE To compile this driver as a module, choose M here: the module will be called aircable. -config USB_SERIAL_AIRPRIME - tristate "USB AirPrime CDMA Wireless Driver" - help - Say Y here if you want to use a AirPrime CDMA Wireless PC card. - - To compile this driver as a module, choose M here: the - module will be called airprime. - config USB_SERIAL_ARK3116 tristate "USB ARK Micro 3116 USB Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 17a762ab6769..6047f818adfe 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -12,7 +12,6 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o -obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index db6f97a93c02..79ea98c66fa8 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -272,7 +272,7 @@ static void aircable_read(struct work_struct *work) * 64 bytes, to ensure I do not get throttled. * Ask USB mailing list for better aproach. */ - tty = port->tty; + tty = port->port.tty; if (!tty) { schedule_work(&priv->rx_work); @@ -378,13 +378,14 @@ static void aircable_shutdown(struct usb_serial *serial) } } -static int aircable_write_room(struct usb_serial_port *port) +static int aircable_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct aircable_private *priv = usb_get_serial_port_data(port); return serial_buf_data_avail(priv->tx_buf); } -static int aircable_write(struct usb_serial_port *port, +static int aircable_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *source, int count) { struct aircable_private *priv = usb_get_serial_port_data(port); @@ -466,7 +467,7 @@ static void aircable_read_bulk_callback(struct urb *urb) if (status) { dbg("%s - urb status = %d", __func__, status); - if (!port->open_count) { + if (!port->port.count) { dbg("%s - port is closed, exiting.", __func__); return; } @@ -494,7 +495,7 @@ static void aircable_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, urb->transfer_buffer); - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { if (urb->actual_length <= 2) { /* This is an incomplete package */ @@ -528,7 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb) } /* Schedule the next read _if_ we are still open */ - if (port->open_count) { + if (port->port.count) { usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), @@ -547,8 +548,9 @@ static void aircable_read_bulk_callback(struct urb *urb) } /* Based on ftdi_sio.c throttle */ -static void aircable_throttle(struct usb_serial_port *port) +static void aircable_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct aircable_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -560,8 +562,9 @@ static void aircable_throttle(struct usb_serial_port *port) } /* Based on ftdi_sio.c unthrottle */ -static void aircable_unthrottle(struct usb_serial_port *port) +static void aircable_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct aircable_private *priv = usb_get_serial_port_data(port); int actually_throttled; unsigned long flags; diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c deleted file mode 100644 index 0798c14ce787..000000000000 --- a/drivers/usb/serial/airprime.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * AirPrime CDMA Wireless Serial USB driver - * - * Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/usb/serial.h> - -static struct usb_device_id id_table [] = { - { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -#define URB_TRANSFER_BUFFER_SIZE 4096 -#define NUM_READ_URBS 4 -#define NUM_WRITE_URBS 4 -#define NUM_BULK_EPS 3 -#define MAX_BULK_EPS 6 - -/* if overridden by the user, then use their value for the size of the - * read and write urbs, and the number of endpoints */ -static int buffer_size = URB_TRANSFER_BUFFER_SIZE; -static int endpoints = NUM_BULK_EPS; -static int debug; -struct airprime_private { - spinlock_t lock; - int outstanding_urbs; - int throttled; - struct urb *read_urbp[NUM_READ_URBS]; - - /* Settings for the port */ - int rts_state; /* Handshaking pins (outputs) */ - int dtr_state; - int cts_state; /* Handshaking pins (inputs) */ - int dsr_state; - int dcd_state; - int ri_state; -}; - -static int airprime_send_setup(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - struct airprime_private *priv; - - dbg("%s", __func__); - - if (port->number != 0) - return 0; - - priv = usb_get_serial_port_data(port); - - if (port->tty) { - int val = 0; - if (priv->dtr_state) - val |= 0x01; - if (priv->rts_state) - val |= 0x02; - - return usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x22, 0x21, val, 0, NULL, 0, - USB_CTRL_SET_TIMEOUT); - } - - return 0; -} - -static void airprime_read_bulk_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - unsigned char *data = urb->transfer_buffer; - struct tty_struct *tty; - int result; - int status = urb->status; - - dbg("%s - port %d", __func__, port->number); - - if (status) { - dbg("%s - nonzero read bulk status received: %d", - __func__, status); - return; - } - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); - - tty = port->tty; - if (tty && urb->actual_length) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); - } - - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, - "%s - failed resubmitting read urb, error %d\n", - __func__, result); - return; -} - -static void airprime_write_bulk_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct airprime_private *priv = usb_get_serial_port_data(port); - int status = urb->status; - unsigned long flags; - - dbg("%s - port %d", __func__, port->number); - - /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree(urb->transfer_buffer); - - if (status) - dbg("%s - nonzero write bulk status received: %d", - __func__, status); - spin_lock_irqsave(&priv->lock, flags); - --priv->outstanding_urbs; - spin_unlock_irqrestore(&priv->lock, flags); - - usb_serial_port_softint(port); -} - -static int airprime_open(struct usb_serial_port *port, struct file *filp) -{ - struct airprime_private *priv = usb_get_serial_port_data(port); - struct usb_serial *serial = port->serial; - struct urb *urb; - char *buffer = NULL; - int i; - int result = 0; - - dbg("%s - port %d", __func__, port->number); - - /* initialize our private data structure if it isn't already created */ - if (!priv) { - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - result = -ENOMEM; - goto out; - } - spin_lock_init(&priv->lock); - usb_set_serial_port_data(port, priv); - } - - /* Set some sane defaults */ - priv->rts_state = 1; - priv->dtr_state = 1; - - for (i = 0; i < NUM_READ_URBS; ++i) { - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) { - dev_err(&port->dev, "%s - out of memory.\n", - __func__); - result = -ENOMEM; - goto errout; - } - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - kfree(buffer); - dev_err(&port->dev, "%s - no more urbs?\n", - __func__); - result = -ENOMEM; - goto errout; - } - usb_fill_bulk_urb(urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - port->bulk_out_endpointAddress), - buffer, buffer_size, - airprime_read_bulk_callback, port); - result = usb_submit_urb(urb, GFP_KERNEL); - if (result) { - usb_free_urb(urb); - kfree(buffer); - dev_err(&port->dev, - "%s - failed submitting read urb %d for port %d, error %d\n", - __func__, i, port->number, result); - goto errout; - } - /* remember this urb so we can kill it when the - port is closed */ - priv->read_urbp[i] = urb; - } - - airprime_send_setup(port); - - goto out; - - errout: - /* some error happened, cancel any submitted urbs and clean up - anything that got allocated successfully */ - - while (i-- != 0) { - urb = priv->read_urbp[i]; - buffer = urb->transfer_buffer; - usb_kill_urb(urb); - usb_free_urb(urb); - kfree(buffer); - } - - out: - return result; -} - -static void airprime_close(struct usb_serial_port *port, struct file *filp) -{ - struct airprime_private *priv = usb_get_serial_port_data(port); - int i; - - dbg("%s - port %d", __func__, port->number); - - priv->rts_state = 0; - priv->dtr_state = 0; - - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) - airprime_send_setup(port); - mutex_unlock(&port->serial->disc_mutex); - - for (i = 0; i < NUM_READ_URBS; ++i) { - usb_kill_urb(priv->read_urbp[i]); - kfree(priv->read_urbp[i]->transfer_buffer); - usb_free_urb(priv->read_urbp[i]); - } - - /* free up private structure */ - kfree(priv); - usb_set_serial_port_data(port, NULL); -} - -static int airprime_write(struct usb_serial_port *port, - const unsigned char *buf, int count) -{ - struct airprime_private *priv = usb_get_serial_port_data(port); - struct usb_serial *serial = port->serial; - struct urb *urb; - unsigned char *buffer; - unsigned long flags; - int status; - dbg("%s - port %d", __func__, port->number); - - spin_lock_irqsave(&priv->lock, flags); - if (priv->outstanding_urbs > NUM_WRITE_URBS) { - spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - write limit hit\n", __func__); - return 0; - } - spin_unlock_irqrestore(&priv->lock, flags); - buffer = kmalloc(count, GFP_ATOMIC); - if (!buffer) { - dev_err(&port->dev, "out of memory\n"); - return -ENOMEM; - } - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - dev_err(&port->dev, "no more free urbs\n"); - kfree(buffer); - return -ENOMEM; - } - memcpy(buffer, buf, count); - - usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); - - usb_fill_bulk_urb(urb, serial->dev, - usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), - buffer, count, - airprime_write_bulk_callback, port); - - /* send it down the pipe */ - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - dev_err(&port->dev, - "%s - usb_submit_urb(write bulk) failed with status = %d\n", - __func__, status); - count = status; - kfree(buffer); - } else { - spin_lock_irqsave(&priv->lock, flags); - ++priv->outstanding_urbs; - spin_unlock_irqrestore(&priv->lock, flags); - } - /* we are done with this urb, so let the host driver - * really free it when it is finished with it */ - usb_free_urb(urb); - return count; -} - -static struct usb_driver airprime_driver = { - .name = "airprime", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; - -static struct usb_serial_driver airprime_device = { - .driver = { - .owner = THIS_MODULE, - .name = "airprime", - }, - .usb_driver = &airprime_driver, - .id_table = id_table, - .open = airprime_open, - .close = airprime_close, - .write = airprime_write, -}; - -static int __init airprime_init(void) -{ - int retval; - - airprime_device.num_ports = endpoints; - if (endpoints < 0 || endpoints >= MAX_BULK_EPS) - airprime_device.num_ports = NUM_BULK_EPS; - - retval = usb_serial_register(&airprime_device); - if (retval) - return retval; - retval = usb_register(&airprime_driver); - if (retval) - usb_serial_deregister(&airprime_device); - return retval; -} - -static void __exit airprime_exit(void) -{ - dbg("%s", __func__); - - usb_deregister(&airprime_driver); - usb_serial_deregister(&airprime_device); -} - -module_init(airprime_init); -module_exit(airprime_exit); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled"); -module_param(buffer_size, int, 0); -MODULE_PARM_DESC(buffer_size, - "Size of the transfer buffers in bytes (default 4096)"); -module_param(endpoints, int, 0); -MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)"); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 77895c8f8f31..aec61880f36c 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -158,12 +158,13 @@ cleanup: return -ENOMEM; } -static void ark3116_set_termios(struct usb_serial_port *port, +static void ark3116_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct ark3116_private *priv = usb_get_serial_port_data(port); - struct ktermios *termios = port->tty->termios; + struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; unsigned long flags; int baud; @@ -177,8 +178,8 @@ static void ark3116_set_termios(struct usb_serial_port *port, spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { - *(port->tty->termios) = tty_std_termios; - port->tty->termios->c_cflag = B9600 | CS8 + *termios = tty_std_termios; + termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; termios->c_ispeed = 9600; termios->c_ospeed = 9600; @@ -192,7 +193,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, buf = kmalloc(1, GFP_KERNEL); if (!buf) { dbg("error kmalloc"); - *port->tty->termios = *old_termios; + *termios = *old_termios; return; } @@ -243,7 +244,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, } /* set baudrate */ - baud = tty_get_baud_rate(port->tty); + baud = tty_get_baud_rate(tty); switch (baud) { case 75: @@ -262,11 +263,11 @@ static void ark3116_set_termios(struct usb_serial_port *port, case 230400: case 460800: /* Report the resulting rate back to the caller */ - tty_encode_baud_rate(port->tty, baud, baud); + tty_encode_baud_rate(tty, baud, baud); break; /* set 9600 as default (if given baudrate is invalid for example) */ default: - tty_encode_baud_rate(port->tty, 9600, 9600); + tty_encode_baud_rate(tty, 9600, 9600); case 0: baud = 9600; } @@ -317,7 +318,8 @@ static void ark3116_set_termios(struct usb_serial_port *port, return; } -static int ark3116_open(struct usb_serial_port *port, struct file *filp) +static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; @@ -332,7 +334,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp) return -ENOMEM; } - result = usb_serial_generic_open(port, filp); + result = usb_serial_generic_open(tty, port, filp); if (result) goto err_out; @@ -362,8 +364,8 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp) ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); /* initialise termios */ - if (port->tty) - ark3116_set_termios(port, &tmp_termios); + if (tty) + ark3116_set_termios(tty, port, &tmp_termios); err_out: kfree(buf); @@ -371,9 +373,10 @@ err_out: return result; } -static int ark3116_ioctl(struct usb_serial_port *port, struct file *file, +static int ark3116_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; @@ -403,8 +406,9 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file, return -ENOIOCTLCMD; } -static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file) +static int ark3116_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; char *buf; char temp; diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 0a322fc53d6e..2ebe06c3405a 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -7,13 +7,14 @@ * This program is largely derived from work by the linux-usb group * and associated source files. Please see the usb/serial files for * individual credits and copyrights. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * TODO: * -- Add true modem contol line query capability. Currently we track the @@ -28,7 +29,8 @@ * compressed all the differnent device entries into 1. * * 30-May-2001 gkh - * switched from using spinlock to a semaphore, which fixes lots of problems. + * switched from using spinlock to a semaphore, which fixes lots of + * problems. * * 08-Apr-2001 gb * - Identify version on module load. @@ -41,7 +43,7 @@ * - Added support for the old Belkin and Peracom devices. * - Made the port able to be opened multiple times. * - Added some defaults incase the line settings are things these devices - * can't support. + * can't support. * * 18-Oct-2000 William Greathouse * Released into the wild (linux-usb-devel) @@ -72,7 +74,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "belkin_sa.h" @@ -87,16 +89,19 @@ static int debug; #define DRIVER_DESC "USB Belkin Serial converter driver" /* function prototypes for a Belkin USB Serial Adapter F5U103 */ -static int belkin_sa_startup (struct usb_serial *serial); -static void belkin_sa_shutdown (struct usb_serial *serial); -static int belkin_sa_open (struct usb_serial_port *port, struct file *filp); -static void belkin_sa_close (struct usb_serial_port *port, struct file *filp); -static void belkin_sa_read_int_callback (struct urb *urb); -static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old); -static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state ); -static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file); -static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); +static int belkin_sa_startup(struct usb_serial *serial); +static void belkin_sa_shutdown(struct usb_serial *serial); +static int belkin_sa_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void belkin_sa_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void belkin_sa_read_int_callback(struct urb *urb); +static void belkin_sa_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios * old); +static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state); +static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file); +static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); static struct usb_device_id id_table_combined [] = { @@ -106,10 +111,10 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(GOHUBS_VID, GOHUBS_PID) }, { USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) }, { USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) }, - { } /* Terminating entry */ + { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver belkin_driver = { .name = "belkin", @@ -131,8 +136,8 @@ static struct usb_serial_driver belkin_device = { .num_ports = 1, .open = belkin_sa_open, .close = belkin_sa_close, - .read_int_callback = belkin_sa_read_int_callback, /* How we get the status info */ - .ioctl = belkin_sa_ioctl, + .read_int_callback = belkin_sa_read_int_callback, + /* How we get the status info */ .set_termios = belkin_sa_set_termios, .break_ctl = belkin_sa_break_ctl, .tiocmget = belkin_sa_tiocmget, @@ -160,12 +165,12 @@ struct belkin_sa_private { #define WDR_TIMEOUT 5000 /* default urb timeout */ /* assumes that struct usb_serial *serial is available */ -#define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \ +#define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \ (c), BELKIN_SA_SET_REQUEST_TYPE, \ (v), 0, NULL, 0, WDR_TIMEOUT) /* do some startup allocations not currently performed by usb_serial_probe() */ -static int belkin_sa_startup (struct usb_serial *serial) +static int belkin_sa_startup(struct usb_serial *serial) { struct usb_device *dev = serial->dev; struct belkin_sa_private *priv; @@ -173,32 +178,35 @@ static int belkin_sa_startup (struct usb_serial *serial) /* allocate the private data structure */ priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL); if (!priv) - return (-1); /* error */ + return -1; /* error */ /* set initial values for control structures */ spin_lock_init(&priv->lock); priv->control_state = 0; priv->last_lsr = 0; priv->last_msr = 0; /* see comments at top of file */ - priv->bad_flow_control = (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0; - info("bcdDevice: %04x, bfc: %d", le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control); + priv->bad_flow_control = + (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0; + info("bcdDevice: %04x, bfc: %d", + le16_to_cpu(dev->descriptor.bcdDevice), + priv->bad_flow_control); init_waitqueue_head(&serial->port[0]->write_wait); usb_set_serial_port_data(serial->port[0], priv); - - return (0); + + return 0; } -static void belkin_sa_shutdown (struct usb_serial *serial) +static void belkin_sa_shutdown(struct usb_serial *serial) { struct belkin_sa_private *priv; int i; - - dbg ("%s", __func__); + + dbg("%s", __func__); /* stop reads and writes on all ports */ - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) { /* My special items, the standard routines free my urbs */ priv = usb_get_serial_port_data(serial->port[i]); kfree(priv); @@ -206,7 +214,8 @@ static void belkin_sa_shutdown (struct usb_serial *serial) } -static int belkin_sa_open (struct usb_serial_port *port, struct file *filp) +static int belkin_sa_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int retval = 0; @@ -235,7 +244,8 @@ exit: } /* belkin_sa_open */ -static void belkin_sa_close (struct usb_serial_port *port, struct file *filp) +static void belkin_sa_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { dbg("%s port %d", __func__, port->number); @@ -246,7 +256,7 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp) } /* belkin_sa_close */ -static void belkin_sa_read_int_callback (struct urb *urb) +static void belkin_sa_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct belkin_sa_private *priv; @@ -272,7 +282,8 @@ static void belkin_sa_read_int_callback (struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); /* Handle known interrupt data */ /* ignore data[0] and data[1] */ @@ -280,7 +291,7 @@ static void belkin_sa_read_int_callback (struct urb *urb) priv = usb_get_serial_port_data(port); spin_lock_irqsave(&priv->lock, flags); priv->last_msr = data[BELKIN_SA_MSR_INDEX]; - + /* Record Control Line states */ if (priv->last_msr & BELKIN_SA_MSR_DSR) priv->control_state |= TIOCM_DSR; @@ -311,7 +322,7 @@ static void belkin_sa_read_int_callback (struct urb *urb) * to look in to this before committing any code. */ if (priv->last_lsr & BELKIN_SA_LSR_ERR) { - tty = port->tty; + tty = port->port.tty; /* Overrun Error */ if (priv->last_lsr & BELKIN_SA_LSR_OE) { } @@ -328,13 +339,14 @@ static void belkin_sa_read_int_callback (struct urb *urb) #endif spin_unlock_irqrestore(&priv->lock, flags); exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err ("%s - usb_submit_urb failed with result %d", + err("%s - usb_submit_urb failed with result %d", __func__, retval); } -static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) +static void belkin_sa_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct belkin_sa_private *priv = usb_get_serial_port_data(port); @@ -347,8 +359,8 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios unsigned long control_state; int bad_flow_control; speed_t baud; - struct ktermios *termios = port->tty->termios; - + struct ktermios *termios = tty->termios; + iflag = termios->c_iflag; cflag = termios->c_cflag; @@ -359,25 +371,26 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios control_state = priv->control_state; bad_flow_control = priv->bad_flow_control; spin_unlock_irqrestore(&priv->lock, flags); - + old_iflag = old_termios->c_iflag; old_cflag = old_termios->c_cflag; /* Set the baud rate */ if ((cflag & CBAUD) != (old_cflag & CBAUD)) { /* reassert DTR and (maybe) RTS on transition from B0 */ - if( (old_cflag&CBAUD) == B0 ) { + if ((old_cflag & CBAUD) == B0) { control_state |= (TIOCM_DTR|TIOCM_RTS); if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0) err("Set DTR error"); /* don't set RTS if using hardware flow control */ if (!(old_cflag & CRTSCTS)) - if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0) + if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST + , 1) < 0) err("Set RTS error"); } } - baud = tty_get_baud_rate(port->tty); + baud = tty_get_baud_rate(tty); if (baud) { urb_value = BELKIN_SA_BAUD(baud); /* Clip to maximum speed */ @@ -387,12 +400,13 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios baud = BELKIN_SA_BAUD(urb_value); /* Report the actual baud rate back to the caller */ - tty_encode_baud_rate(port->tty, baud, baud); + tty_encode_baud_rate(tty, baud, baud); if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0) err("Set baudrate error"); } else { /* Disable flow control */ - if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0) + if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, + BELKIN_SA_FLOW_NONE) < 0) err("Disable flowcontrol error"); /* Drop RTS and DTR */ control_state &= ~(TIOCM_DTR | TIOCM_RTS); @@ -403,9 +417,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios } /* set the parity */ - if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) { + if ((cflag ^ old_cflag) & (PARENB | PARODD)) { if (cflag & PARENB) - urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD : BELKIN_SA_PARITY_EVEN; + urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD + : BELKIN_SA_PARITY_EVEN; else urb_value = BELKIN_SA_PARITY_NONE; if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0) @@ -413,31 +428,40 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios } /* set the number of data bits */ - if( (cflag&CSIZE) != (old_cflag&CSIZE) ) { + if ((cflag & CSIZE) != (old_cflag & CSIZE)) { switch (cflag & CSIZE) { - case CS5: urb_value = BELKIN_SA_DATA_BITS(5); break; - case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break; - case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break; - case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break; - default: dbg("CSIZE was not CS5-CS8, using default of 8"); - urb_value = BELKIN_SA_DATA_BITS(8); - break; + case CS5: + urb_value = BELKIN_SA_DATA_BITS(5); + break; + case CS6: + urb_value = BELKIN_SA_DATA_BITS(6); + break; + case CS7: + urb_value = BELKIN_SA_DATA_BITS(7); + break; + case CS8: + urb_value = BELKIN_SA_DATA_BITS(8); + break; + default: dbg("CSIZE was not CS5-CS8, using default of 8"); + urb_value = BELKIN_SA_DATA_BITS(8); + break; } if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0) err("Set data bits error"); } /* set the number of stop bits */ - if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) { - urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2) : BELKIN_SA_STOP_BITS(1); - if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST, urb_value) < 0) + if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { + urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2) + : BELKIN_SA_STOP_BITS(1); + if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST, + urb_value) < 0) err("Set stop bits error"); } /* Set flow control */ - if( (iflag&IXOFF) != (old_iflag&IXOFF) - || (iflag&IXON) != (old_iflag&IXON) - || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { + if (((iflag ^ old_iflag) & (IXOFF | IXON)) || + ((cflag ^ old_cflag) & CRTSCTS)) { urb_value = 0; if ((iflag & IXOFF) || (iflag & IXON)) urb_value |= (BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON); @@ -463,8 +487,9 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios } /* belkin_sa_set_termios */ -static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state ) +static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0) @@ -472,12 +497,13 @@ static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state ) } -static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file) +static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct belkin_sa_private *priv = usb_get_serial_port_data(port); unsigned long control_state; unsigned long flags; - + dbg("%s", __func__); spin_lock_irqsave(&priv->lock, flags); @@ -488,9 +514,10 @@ static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file) } -static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file, +static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; struct belkin_sa_private *priv = usb_get_serial_port_data(port); unsigned long control_state; @@ -498,7 +525,7 @@ static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file, int retval; int rts = 0; int dtr = 0; - + dbg("%s", __func__); spin_lock_irqsave(&priv->lock, flags); @@ -540,29 +567,7 @@ exit: } -static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case TIOCMIWAIT: - /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ - /* TODO */ - return( 0 ); - - case TIOCGICOUNT: - /* return count of modemline transitions */ - /* TODO */ - return 0; - - default: - dbg("belkin_sa_ioctl arg not supported - 0x%04x",cmd); - return(-ENOIOCTLCMD); - break; - } - return 0; -} /* belkin_sa_ioctl */ - - -static int __init belkin_sa_init (void) +static int __init belkin_sa_init(void) { int retval; retval = usb_serial_register(&belkin_device); @@ -582,17 +587,17 @@ failed_usb_serial_register: static void __exit belkin_sa_exit (void) { - usb_deregister (&belkin_driver); - usb_serial_deregister (&belkin_device); + usb_deregister(&belkin_driver); + usb_serial_deregister(&belkin_device); } -module_init (belkin_sa_init); -module_exit (belkin_sa_exit); +module_init(belkin_sa_init); +module_exit(belkin_sa_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_VERSION( DRIVER_VERSION ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/belkin_sa.h b/drivers/usb/serial/belkin_sa.h index 9116b92f4622..c66a6730d38c 100644 --- a/drivers/usb/serial/belkin_sa.h +++ b/drivers/usb/serial/belkin_sa.h @@ -7,13 +7,14 @@ * This program is largely derived from work by the linux-usb group * and associated source files. Please see the usb/serial files for * individual credits and copyrights. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * 12-Mar-2001 gkh * Added GoHubs GO-COM232 device id. @@ -27,7 +28,7 @@ * adapter, so pardon any stupid mistakes. All of the information * I am using to write this driver was acquired by using a modified * UsbSnoop on Windows2000. - * + * */ #ifndef __LINUX_USB_SERIAL_BSA_H @@ -96,20 +97,20 @@ /* * It seems that the interrupt pipe is closely modelled after the - * 16550 register layout. This is probably because the adapter can + * 16550 register layout. This is probably because the adapter can * be used in a "DOS" environment to simulate a standard hardware port. */ -#define BELKIN_SA_LSR_INDEX 2 /* Line Status Register */ +#define BELKIN_SA_LSR_INDEX 2 /* Line Status Register */ #define BELKIN_SA_LSR_RDR 0x01 /* receive data ready */ #define BELKIN_SA_LSR_OE 0x02 /* overrun error */ #define BELKIN_SA_LSR_PE 0x04 /* parity error */ #define BELKIN_SA_LSR_FE 0x08 /* framing error */ #define BELKIN_SA_LSR_BI 0x10 /* break indicator */ -#define BELKIN_SA_LSR_THE 0x20 /* transmit holding register empty */ +#define BELKIN_SA_LSR_THE 0x20 /* tx holding register empty */ #define BELKIN_SA_LSR_TE 0x40 /* transmit register empty */ #define BELKIN_SA_LSR_ERR 0x80 /* OE | PE | FE | BI */ -#define BELKIN_SA_MSR_INDEX 3 /* Modem Status Register */ +#define BELKIN_SA_MSR_INDEX 3 /* Modem Status Register */ #define BELKIN_SA_MSR_DCTS 0x01 /* Delta CTS */ #define BELKIN_SA_MSR_DDSR 0x02 /* Delta DSR */ #define BELKIN_SA_MSR_DRI 0x04 /* Delta RI */ diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 0b14aea8ebd5..83bbb5bca2ef 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -15,7 +15,8 @@ #include <linux/usb.h> #include <linux/usb/serial.h> -static int usb_serial_device_match (struct device *dev, struct device_driver *drv) +static int usb_serial_device_match(struct device *dev, + struct device_driver *drv) { struct usb_serial_driver *driver; const struct usb_serial_port *port; @@ -46,7 +47,7 @@ static ssize_t show_port_number(struct device *dev, static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL); -static int usb_serial_device_probe (struct device *dev) +static int usb_serial_device_probe(struct device *dev) { struct usb_serial_driver *driver; struct usb_serial_port *port; @@ -66,7 +67,7 @@ static int usb_serial_device_probe (struct device *dev) retval = -EIO; goto exit; } - retval = driver->port_probe (port); + retval = driver->port_probe(port); module_put(driver->driver.owner); if (retval) goto exit; @@ -77,8 +78,8 @@ static int usb_serial_device_probe (struct device *dev) goto exit; minor = port->number; - tty_register_device (usb_serial_tty_driver, minor, dev); - dev_info(&port->serial->dev->dev, + tty_register_device(usb_serial_tty_driver, minor, dev); + dev_info(&port->serial->dev->dev, "%s converter now attached to ttyUSB%d\n", driver->description, minor); @@ -86,7 +87,7 @@ exit: return retval; } -static int usb_serial_device_remove (struct device *dev) +static int usb_serial_device_remove(struct device *dev) { struct usb_serial_driver *driver; struct usb_serial_port *port; @@ -94,9 +95,8 @@ static int usb_serial_device_remove (struct device *dev) int minor; port = to_usb_serial_port(dev); - if (!port) { + if (!port) return -ENODEV; - } device_remove_file(&port->dev, &dev_attr_port_number); @@ -107,12 +107,12 @@ static int usb_serial_device_remove (struct device *dev) retval = -EIO; goto exit; } - retval = driver->port_remove (port); + retval = driver->port_remove(port); module_put(driver->driver.owner); } exit: minor = port->number; - tty_unregister_device (usb_serial_tty_driver, minor); + tty_unregister_device(usb_serial_tty_driver, minor); dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", driver->description, minor); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 1f7c86bd8297..f61e3ca64305 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -232,7 +232,8 @@ error: kfree(priv); } /* open this device, set default parameters */ -static int ch341_open(struct usb_serial_port *port, struct file *filp) +static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { struct usb_serial *serial = port->serial; struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); @@ -256,7 +257,7 @@ static int ch341_open(struct usb_serial_port *port, struct file *filp) if (r) goto out; - r = usb_serial_generic_open(port, filp); + r = usb_serial_generic_open(tty, port, filp); out: return r; } @@ -264,11 +265,10 @@ out: return r; /* Old_termios contains the original termios settings and * tty->termios contains the new setting to be used. */ -static void ch341_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) +static void ch341_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct ch341_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty = port->tty; unsigned baud_rate; dbg("ch341_set_termios()"); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 201184c3fb87..7b74238ad1c7 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -6,7 +6,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. - * + * * Thanks to Randy Dunlap for the original version of this code. * */ @@ -67,7 +67,7 @@ static int usb_console_setup(struct console *co, char *options) struct tty_struct *tty = NULL; struct ktermios *termios = NULL, dummy; - dbg ("%s", __func__); + dbg("%s", __func__); if (options) { baud = simple_strtoul(options, NULL, 10); @@ -81,55 +81,27 @@ static int usb_console_setup(struct console *co, char *options) if (*s) doflow = (*s++ == 'r'); } + + /* Sane default */ + if (baud == 0) + baud = 9600; - /* build a cflag setting */ - switch (baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - /* - * Set this to a sane value to prevent a divide error - */ - baud = 9600; - break; - } switch (bits) { - case 7: - cflag |= CS7; - break; - default: - case 8: - cflag |= CS8; - break; + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; } switch (parity) { - case 'o': case 'O': - cflag |= PARODD; - break; - case 'e': case 'E': - cflag |= PARENB; - break; + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; } co->cflag = cflag; @@ -140,17 +112,17 @@ static int usb_console_setup(struct console *co, char *options) serial = usb_serial_get_by_index(co->index); if (serial == NULL) { /* no device is connected yet, sorry :( */ - err ("No USB device connected to ttyUSB%i", co->index); + err("No USB device connected to ttyUSB%i", co->index); return -ENODEV; } port = serial->port[0]; - port->tty = NULL; + port->port.tty = NULL; info->port = port; - - ++port->open_count; - if (port->open_count == 1) { + + ++port->port.count; + if (port->port.count == 1) { if (serial->type->set_termios) { /* * allocate a fake tty so the driver can initialize @@ -171,15 +143,15 @@ static int usb_console_setup(struct console *co, char *options) } memset(&dummy, 0, sizeof(struct ktermios)); tty->termios = termios; - port->tty = tty; + port->port.tty = tty; } - /* only call the device specific open if this + /* only call the device specific open if this * is the first time the port is opened */ if (serial->type->open) - retval = serial->type->open(port, NULL); + retval = serial->type->open(NULL, port, NULL); else - retval = usb_serial_generic_open(port, NULL); + retval = usb_serial_generic_open(NULL, port, NULL); if (retval) { err("could not open USB console port"); @@ -188,9 +160,10 @@ static int usb_console_setup(struct console *co, char *options) if (serial->type->set_termios) { termios->c_cflag = cflag; - serial->type->set_termios(port, &dummy); + tty_termios_encode_baud_rate(termios, baud, baud); + serial->type->set_termios(NULL, port, &dummy); - port->tty = NULL; + port->port.tty = NULL; kfree(termios); kfree(tty); } @@ -203,15 +176,16 @@ out: return retval; free_termios: kfree(termios); - port->tty = NULL; + port->port.tty = NULL; free_tty: kfree(tty); reset_open_count: - port->open_count = 0; + port->port.count = 0; goto out; } -static void usb_console_write(struct console *co, const char *buf, unsigned count) +static void usb_console_write(struct console *co, + const char *buf, unsigned count) { static struct usbcons_info *info = &usbcons_info; struct usb_serial_port *port = info->port; @@ -227,8 +201,8 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun dbg("%s - port %d, %d byte(s)", __func__, port->number, count); - if (!port->open_count) { - dbg ("%s - port not opened", __func__); + if (!port->port.count) { + dbg("%s - port not opened", __func__); return; } @@ -236,26 +210,29 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun unsigned int i; unsigned int lf; /* search for LF so we can insert CR if necessary */ - for (i=0, lf=0 ; i < count ; i++) { + for (i = 0, lf = 0 ; i < count ; i++) { if (*(buf + i) == 10) { lf = 1; i++; break; } } - /* pass on to the driver specific version of this function if it is available */ + /* pass on to the driver specific version of this function if + it is available */ if (serial->type->write) - retval = serial->type->write(port, buf, i); + retval = serial->type->write(NULL, port, buf, i); else - retval = usb_serial_generic_write(port, buf, i); + retval = usb_serial_generic_write(NULL, port, buf, i); dbg("%s - return value : %d", __func__, retval); if (lf) { /* append CR after LF */ unsigned char cr = 13; if (serial->type->write) - retval = serial->type->write(port, &cr, 1); + retval = serial->type->write(NULL, + port, &cr, 1); else - retval = usb_serial_generic_write(port, &cr, 1); + retval = usb_serial_generic_write(NULL, + port, &cr, 1); dbg("%s - return value : %d", __func__, retval); } buf += i; @@ -273,18 +250,19 @@ static struct console usbcons = { void usb_serial_console_disconnect(struct usb_serial *serial) { - if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) { + if (serial && serial->port && serial->port[0] + && serial->port[0] == usbcons_info.port) { usb_serial_console_exit(); usb_serial_put(serial); } } -void usb_serial_console_init (int serial_debug, int minor) +void usb_serial_console_init(int serial_debug, int minor) { debug = serial_debug; if (minor == 0) { - /* + /* * Call register_console() if this is the first device plugged * in. If we call it earlier, then the callback to * console_setup() will fail, as there is not a device seen by @@ -293,21 +271,21 @@ void usb_serial_console_init (int serial_debug, int minor) /* * Register console. * NOTES: - * console_setup() is called (back) immediately (from register_console). - * console_write() is called immediately from register_console iff - * CON_PRINTBUFFER is set in flags. + * console_setup() is called (back) immediately (from + * register_console). console_write() is called immediately + * from register_console iff CON_PRINTBUFFER is set in flags. */ - dbg ("registering the USB serial console."); + dbg("registering the USB serial console."); register_console(&usbcons); } } -void usb_serial_console_exit (void) +void usb_serial_console_exit(void) { if (usbcons_info.port) { unregister_console(&usbcons); - if (usbcons_info.port->open_count) - usbcons_info.port->open_count--; + if (usbcons_info.port->port.count) + usbcons_info.port->port.count--; usbcons_info.port = NULL; } } diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index f5b57b196c5a..442cba69cce5 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -25,7 +25,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/usb.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb/serial.h> /* @@ -37,17 +37,20 @@ /* * Function Prototypes */ -static int cp2101_open(struct usb_serial_port*, struct file*); -static void cp2101_cleanup(struct usb_serial_port*); -static void cp2101_close(struct usb_serial_port*, struct file*); -static void cp2101_get_termios(struct usb_serial_port*); -static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*); -static int cp2101_tiocmget (struct usb_serial_port *, struct file *); -static int cp2101_tiocmset (struct usb_serial_port *, struct file *, +static int cp2101_open(struct tty_struct *, struct usb_serial_port *, + struct file *); +static void cp2101_cleanup(struct usb_serial_port *); +static void cp2101_close(struct tty_struct *, struct usb_serial_port *, + struct file*); +static void cp2101_get_termios(struct tty_struct *); +static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, + struct ktermios*); +static int cp2101_tiocmget(struct tty_struct *, struct file *); +static int cp2101_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); -static void cp2101_break_ctl(struct usb_serial_port*, int); -static int cp2101_startup (struct usb_serial *); -static void cp2101_shutdown(struct usb_serial*); +static void cp2101_break_ctl(struct tty_struct *, int); +static int cp2101_startup(struct usb_serial *); +static void cp2101_shutdown(struct usb_serial *); static int debug; @@ -93,7 +96,7 @@ static struct usb_device_id id_table [] = { { } /* Terminating Entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver cp2101_driver = { .name = "cp2101", @@ -182,7 +185,7 @@ static struct usb_serial_driver cp2101_device = { * 'data' is a pointer to a pre-allocated array of integers large * enough to hold 'size' bytes (with 4 bytes to each integer) */ -static int cp2101_get_config(struct usb_serial_port* port, u8 request, +static int cp2101_get_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; @@ -202,12 +205,12 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request, request++; /* Issue the request, attempting to read 'size' bytes */ - result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0), + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_DEVICE_TO_HOST, 0x0000, 0, buf, size, 300); /* Convert data into an array of integers */ - for (i=0; i<length; i++) + for (i = 0; i < length; i++) data[i] = le32_to_cpu(buf[i]); kfree(buf); @@ -228,7 +231,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request, * Values less than 16 bits wide are sent directly * 'size' is specified in bytes. */ -static int cp2101_set_config(struct usb_serial_port* port, u8 request, +static int cp2101_set_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; @@ -250,12 +253,12 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request, buf[i] = cpu_to_le32(data[i]); if (size > 2) { - result = usb_control_msg (serial->dev, + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, 0x0000, 0, buf, size, 300); } else { - result = usb_control_msg (serial->dev, + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, data[0], 0, NULL, 0, 300); @@ -271,7 +274,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request, } /* Single data value */ - result = usb_control_msg (serial->dev, + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, data[0], 0, NULL, 0, 300); @@ -283,13 +286,14 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request, * Convenience function for calling cp2101_set_config on single data values * without requiring an integer pointer */ -static inline int cp2101_set_config_single(struct usb_serial_port* port, +static inline int cp2101_set_config_single(struct usb_serial_port *port, u8 request, unsigned int data) { return cp2101_set_config(port, request, &data, 2); } -static int cp2101_open (struct usb_serial_port *port, struct file *filp) +static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { struct usb_serial *serial = port->serial; int result; @@ -303,7 +307,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp) } /* Start reading from the device */ - usb_fill_bulk_urb (port->read_urb, serial->dev, + usb_fill_bulk_urb(port->read_urb, serial->dev, usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, @@ -318,15 +322,15 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp) } /* Configure the termios structure */ - cp2101_get_termios(port); + cp2101_get_termios(tty); /* Set the DTR and RTS pins low */ - cp2101_tiocmset(port, NULL, TIOCM_DTR | TIOCM_RTS, 0); + cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); return 0; } -static void cp2101_cleanup (struct usb_serial_port *port) +static void cp2101_cleanup(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; @@ -341,7 +345,8 @@ static void cp2101_cleanup (struct usb_serial_port *port) } } -static void cp2101_close (struct usb_serial_port *port, struct file * filp) +static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { dbg("%s - port %d", __func__, port->number); @@ -362,19 +367,15 @@ static void cp2101_close (struct usb_serial_port *port, struct file * filp) * from the device, corrects any unsupported values, and configures the * termios structure to reflect the state of the device */ -static void cp2101_get_termios (struct usb_serial_port *port) +static void cp2101_get_termios (struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; unsigned int cflag, modem_ctl[4]; - int baud; - int bits; + unsigned int baud; + unsigned int bits; dbg("%s - port %d", __func__, port->number); - if (!port->tty || !port->tty->termios) { - dbg("%s - no tty structures", __func__); - return; - } - cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ if (baud) @@ -382,104 +383,102 @@ static void cp2101_get_termios (struct usb_serial_port *port) dbg("%s - baud rate = %d", __func__, baud); - tty_encode_baud_rate(port->tty, baud, baud); - cflag = port->tty->termios->c_cflag; + tty_encode_baud_rate(tty, baud, baud); + cflag = tty->termios->c_cflag; cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; - switch(bits & BITS_DATA_MASK) { - case BITS_DATA_5: - dbg("%s - data bits = 5", __func__); - cflag |= CS5; - break; - case BITS_DATA_6: - dbg("%s - data bits = 6", __func__); - cflag |= CS6; - break; - case BITS_DATA_7: - dbg("%s - data bits = 7", __func__); - cflag |= CS7; - break; - case BITS_DATA_8: - dbg("%s - data bits = 8", __func__); - cflag |= CS8; - break; - case BITS_DATA_9: - dbg("%s - data bits = 9 (not supported, " - "using 8 data bits)", __func__); - cflag |= CS8; - bits &= ~BITS_DATA_MASK; - bits |= BITS_DATA_8; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - default: - dbg("%s - Unknown number of data bits, " - "using 8", __func__); - cflag |= CS8; - bits &= ~BITS_DATA_MASK; - bits |= BITS_DATA_8; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; + switch (bits & BITS_DATA_MASK) { + case BITS_DATA_5: + dbg("%s - data bits = 5", __func__); + cflag |= CS5; + break; + case BITS_DATA_6: + dbg("%s - data bits = 6", __func__); + cflag |= CS6; + break; + case BITS_DATA_7: + dbg("%s - data bits = 7", __func__); + cflag |= CS7; + break; + case BITS_DATA_8: + dbg("%s - data bits = 8", __func__); + cflag |= CS8; + break; + case BITS_DATA_9: + dbg("%s - data bits = 9 (not supported, using 8 data bits)", + __func__); + cflag |= CS8; + bits &= ~BITS_DATA_MASK; + bits |= BITS_DATA_8; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + default: + dbg("%s - Unknown number of data bits, using 8", __func__); + cflag |= CS8; + bits &= ~BITS_DATA_MASK; + bits |= BITS_DATA_8; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; } - switch(bits & BITS_PARITY_MASK) { - case BITS_PARITY_NONE: - dbg("%s - parity = NONE", __func__); - cflag &= ~PARENB; - break; - case BITS_PARITY_ODD: - dbg("%s - parity = ODD", __func__); - cflag |= (PARENB|PARODD); - break; - case BITS_PARITY_EVEN: - dbg("%s - parity = EVEN", __func__); - cflag &= ~PARODD; - cflag |= PARENB; - break; - case BITS_PARITY_MARK: - dbg("%s - parity = MARK (not supported, " - "disabling parity)", __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - case BITS_PARITY_SPACE: - dbg("%s - parity = SPACE (not supported, " - "disabling parity)", __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - default: - dbg("%s - Unknown parity mode, " - "disabling parity", __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; + switch (bits & BITS_PARITY_MASK) { + case BITS_PARITY_NONE: + dbg("%s - parity = NONE", __func__); + cflag &= ~PARENB; + break; + case BITS_PARITY_ODD: + dbg("%s - parity = ODD", __func__); + cflag |= (PARENB|PARODD); + break; + case BITS_PARITY_EVEN: + dbg("%s - parity = EVEN", __func__); + cflag &= ~PARODD; + cflag |= PARENB; + break; + case BITS_PARITY_MARK: + dbg("%s - parity = MARK (not supported, disabling parity)", + __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + case BITS_PARITY_SPACE: + dbg("%s - parity = SPACE (not supported, disabling parity)", + __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + default: + dbg("%s - Unknown parity mode, disabling parity", __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; } cflag &= ~CSTOPB; - switch(bits & BITS_STOP_MASK) { - case BITS_STOP_1: - dbg("%s - stop bits = 1", __func__); - break; - case BITS_STOP_1_5: - dbg("%s - stop bits = 1.5 (not supported, " - "using 1 stop bit)", __func__); - bits &= ~BITS_STOP_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - case BITS_STOP_2: - dbg("%s - stop bits = 2", __func__); - cflag |= CSTOPB; - break; - default: - dbg("%s - Unknown number of stop bits, " - "using 1 stop bit", __func__); - bits &= ~BITS_STOP_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; + switch (bits & BITS_STOP_MASK) { + case BITS_STOP_1: + dbg("%s - stop bits = 1", __func__); + break; + case BITS_STOP_1_5: + dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", + __func__); + bits &= ~BITS_STOP_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + case BITS_STOP_2: + dbg("%s - stop bits = 2", __func__); + cflag |= CSTOPB; + break; + default: + dbg("%s - Unknown number of stop bits, using 1 stop bit", + __func__); + bits &= ~BITS_STOP_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; } cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); @@ -491,55 +490,53 @@ static void cp2101_get_termios (struct usb_serial_port *port) cflag &= ~CRTSCTS; } - port->tty->termios->c_cflag = cflag; + tty->termios->c_cflag = cflag; } -static void cp2101_set_termios (struct usb_serial_port *port, - struct ktermios *old_termios) +static void cp2101_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; - int baud=0, bits; + unsigned int baud = 0, bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); - if (!port->tty || !port->tty->termios) { - dbg("%s - no tty structures", __func__); + if (!tty) return; - } - port->tty->termios->c_cflag &= ~CMSPAR; - cflag = port->tty->termios->c_cflag; + tty->termios->c_cflag &= ~CMSPAR; + cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - baud = tty_get_baud_rate(port->tty); + baud = tty_get_baud_rate(tty); /* If the baud rate is to be updated*/ if (baud != tty_termios_baud_rate(old_termios)) { switch (baud) { - case 0: - case 600: - case 1200: - case 1800: - case 2400: - case 4800: - case 7200: - case 9600: - case 14400: - case 19200: - case 28800: - case 38400: - case 55854: - case 57600: - case 115200: - case 127117: - case 230400: - case 460800: - case 921600: - case 3686400: - break; - default: - baud = 9600; - break; + case 0: + case 600: + case 1200: + case 1800: + case 2400: + case 4800: + case 7200: + case 9600: + case 14400: + case 19200: + case 28800: + case 38400: + case 55854: + case 57600: + case 115200: + case 127117: + case 230400: + case 460800: + case 921600: + case 3686400: + break; + default: + baud = 9600; + break; } if (baud) { @@ -554,35 +551,35 @@ static void cp2101_set_termios (struct usb_serial_port *port, } } /* Report back the resulting baud rate */ - tty_encode_baud_rate(port->tty, baud, baud); + tty_encode_baud_rate(tty, baud, baud); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { cp2101_get_config(port, CP2101_BITS, &bits, 2); bits &= ~BITS_DATA_MASK; switch (cflag & CSIZE) { - case CS5: - bits |= BITS_DATA_5; - dbg("%s - data bits = 5", __func__); - break; - case CS6: - bits |= BITS_DATA_6; - dbg("%s - data bits = 6", __func__); - break; - case CS7: - bits |= BITS_DATA_7; - dbg("%s - data bits = 7", __func__); - break; - case CS8: - bits |= BITS_DATA_8; - dbg("%s - data bits = 8", __func__); - break; - /*case CS9: - bits |= BITS_DATA_9; - dbg("%s - data bits = 9", __func__); - break;*/ - default: - dev_err(&port->dev, "cp2101 driver does not " + case CS5: + bits |= BITS_DATA_5; + dbg("%s - data bits = 5", __func__); + break; + case CS6: + bits |= BITS_DATA_6; + dbg("%s - data bits = 6", __func__); + break; + case CS7: + bits |= BITS_DATA_7; + dbg("%s - data bits = 7", __func__); + break; + case CS8: + bits |= BITS_DATA_8; + dbg("%s - data bits = 8", __func__); + break; + /*case CS9: + bits |= BITS_DATA_9; + dbg("%s - data bits = 9", __func__); + break;*/ + default: + dev_err(&port->dev, "cp2101 driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; @@ -651,10 +648,11 @@ static void cp2101_set_termios (struct usb_serial_port *port, } -static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file, +static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - int control = 0; + struct usb_serial_port *port = tty->driver_data; + unsigned int control = 0; dbg("%s - port %d", __func__, port->number); @@ -681,9 +679,11 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file, } -static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file) +static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) { - int control, result; + struct usb_serial_port *port = tty->driver_data; + unsigned int control; + int result; dbg("%s - port %d", __func__, port->number); @@ -701,9 +701,10 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file) return result; } -static void cp2101_break_ctl (struct usb_serial_port *port, int break_state) +static void cp2101_break_ctl (struct tty_struct *tty, int break_state) { - int state; + struct usb_serial_port *port = tty->driver_data; + unsigned int state; dbg("%s - port %d", __func__, port->number); if (break_state == 0) @@ -711,30 +712,29 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state) else state = BREAK_ON; dbg("%s - turning break %s", __func__, - state==BREAK_OFF ? "off" : "on"); + state == BREAK_OFF ? "off" : "on"); cp2101_set_config(port, CP2101_BREAK, &state, 2); } -static int cp2101_startup (struct usb_serial *serial) +static int cp2101_startup(struct usb_serial *serial) { /* CP2101 buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); return 0; } -static void cp2101_shutdown (struct usb_serial *serial) +static void cp2101_shutdown(struct usb_serial *serial) { int i; dbg("%s", __func__); /* Stop reads and writes on all ports */ - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) cp2101_cleanup(serial->port[i]); - } } -static int __init cp2101_init (void) +static int __init cp2101_init(void) { int retval; @@ -754,10 +754,10 @@ static int __init cp2101_init (void) return 0; } -static void __exit cp2101_exit (void) +static void __exit cp2101_exit(void) { - usb_deregister (&cp2101_driver); - usb_serial_deregister (&cp2101_device); + usb_deregister(&cp2101_driver); + usb_serial_deregister(&cp2101_device); } module_init(cp2101_init); diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index c164e2cf2752..b4d72351cb96 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -37,7 +37,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -57,22 +57,25 @@ static int debug; #define CYBERJACK_PRODUCT_ID 0x0100 /* Function prototypes */ -static int cyberjack_startup (struct usb_serial *serial); -static void cyberjack_shutdown (struct usb_serial *serial); -static int cyberjack_open (struct usb_serial_port *port, struct file *filp); -static void cyberjack_close (struct usb_serial_port *port, struct file *filp); -static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static int cyberjack_write_room( struct usb_serial_port *port ); -static void cyberjack_read_int_callback (struct urb *urb); -static void cyberjack_read_bulk_callback (struct urb *urb); -static void cyberjack_write_bulk_callback (struct urb *urb); +static int cyberjack_startup(struct usb_serial *serial); +static void cyberjack_shutdown(struct usb_serial *serial); +static int cyberjack_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void cyberjack_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static int cyberjack_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count); +static int cyberjack_write_room(struct tty_struct *tty); +static void cyberjack_read_int_callback(struct urb *urb); +static void cyberjack_read_bulk_callback(struct urb *urb); +static void cyberjack_write_bulk_callback(struct urb *urb); static struct usb_device_id id_table [] = { { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver cyberjack_driver = { .name = "cyberjack", @@ -111,7 +114,7 @@ struct cyberjack_private { }; /* do some startup allocations not currently performed by usb_serial_probe() */ -static int cyberjack_startup (struct usb_serial *serial) +static int cyberjack_startup(struct usb_serial *serial) { struct cyberjack_private *priv; int i; @@ -135,20 +138,20 @@ static int cyberjack_startup (struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { int result; serial->port[i]->interrupt_in_urb->dev = serial->dev; - result = usb_submit_urb(serial->port[i]->interrupt_in_urb, + result = usb_submit_urb(serial->port[i]->interrupt_in_urb, GFP_KERNEL); if (result) err(" usb_submit_urb(read int) failed"); dbg("%s - usb_submit_urb(int urb)", __func__); } - return( 0 ); + return 0; } -static void cyberjack_shutdown (struct usb_serial *serial) +static void cyberjack_shutdown(struct usb_serial *serial) { int i; - + dbg("%s", __func__); for (i = 0; i < serial->num_ports; ++i) { @@ -158,8 +161,9 @@ static void cyberjack_shutdown (struct usb_serial *serial) usb_set_serial_port_data(serial->port[i], NULL); } } - -static int cyberjack_open (struct usb_serial_port *port, struct file *filp) + +static int cyberjack_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct cyberjack_private *priv; unsigned long flags; @@ -167,14 +171,15 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp) dbg("%s - port %d", __func__, port->number); - dbg("%s - usb_clear_halt", __func__ ); + dbg("%s - usb_clear_halt", __func__); usb_clear_halt(port->serial->dev, port->write_urb->pipe); /* force low_latency on so that our tty_push actually forces * the data through, otherwise it is scheduled, and with high * data rates (like with OHCI) data can get lost. */ - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; priv = usb_get_serial_port_data(port); spin_lock_irqsave(&priv->lock, flags); @@ -186,7 +191,8 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp) return result; } -static void cyberjack_close (struct usb_serial_port *port, struct file *filp) +static void cyberjack_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __func__, port->number); @@ -197,7 +203,8 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp) } } -static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count) +static int cyberjack_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct cyberjack_private *priv = usb_get_serial_port_data(port); @@ -223,7 +230,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b spin_lock_irqsave(&priv->lock, flags); - if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) { + if (count+priv->wrfilled > sizeof(priv->wrbuf)) { /* To much data for buffer. Reset buffer. */ priv->wrfilled = 0; port->write_urb_busy = 0; @@ -232,42 +239,43 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b } /* Copy data */ - memcpy (priv->wrbuf+priv->wrfilled, buf, count); + memcpy(priv->wrbuf + priv->wrfilled, buf, count); usb_serial_debug_data(debug, &port->dev, __func__, count, - priv->wrbuf+priv->wrfilled); + priv->wrbuf + priv->wrfilled); priv->wrfilled += count; - if( priv->wrfilled >= 3 ) { + if (priv->wrfilled >= 3) { wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; dbg("%s - expected data: %d", __func__, wrexpected); - } else { + } else wrexpected = sizeof(priv->wrbuf); - } - if( priv->wrfilled >= wrexpected ) { + if (priv->wrfilled >= wrexpected) { /* We have enough data to begin transmission */ int length; dbg("%s - transmitting data (frame 1)", __func__); - length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected; + length = (wrexpected > port->bulk_out_size) ? + port->bulk_out_size : wrexpected; - memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length ); - priv->wrsent=length; + memcpy(port->write_urb->transfer_buffer, priv->wrbuf, length); + priv->wrsent = length; /* set up our urb */ - usb_fill_bulk_urb(port->write_urb, serial->dev, + usb_fill_bulk_urb(port->write_urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, length, - ((serial->type->write_bulk_callback) ? - serial->type->write_bulk_callback : - cyberjack_write_bulk_callback), + ((serial->type->write_bulk_callback) ? + serial->type->write_bulk_callback : + cyberjack_write_bulk_callback), port); /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", __func__, result); + err("%s - failed submitting write urb, error %d", + __func__, result); /* Throw away data. No better idea what to do with it. */ priv->wrfilled = 0; priv->wrsent = 0; @@ -276,12 +284,12 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b return 0; } - dbg("%s - priv->wrsent=%d", __func__,priv->wrsent); - dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled); + dbg("%s - priv->wrsent=%d", __func__, priv->wrsent); + dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled); - if( priv->wrsent>=priv->wrfilled ) { + if (priv->wrsent >= priv->wrfilled) { dbg("%s - buffer cleaned", __func__); - memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); + memset(priv->wrbuf, 0, sizeof(priv->wrbuf)); priv->wrfilled = 0; priv->wrsent = 0; } @@ -289,16 +297,16 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b spin_unlock_irqrestore(&priv->lock, flags); - return (count); -} + return count; +} -static int cyberjack_write_room( struct usb_serial_port *port ) +static int cyberjack_write_room(struct tty_struct *tty) { /* FIXME: .... */ return CYBERJACK_LOCAL_BUF_SIZE; } -static void cyberjack_read_int_callback( struct urb *urb ) +static void cyberjack_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); @@ -312,10 +320,11 @@ static void cyberjack_read_int_callback( struct urb *urb ) if (status) return; - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); /* React only to interrupts signaling a bulk_in transfer */ - if( (urb->actual_length == 4) && (data[0] == 0x01) ) { + if (urb->actual_length == 4 && data[0] == 0x01) { short old_rdtodo; /* This is a announcement of coming bulk_ins. */ @@ -325,8 +334,8 @@ static void cyberjack_read_int_callback( struct urb *urb ) old_rdtodo = priv->rdtodo; - if( (old_rdtodo+size)<(old_rdtodo) ) { - dbg( "To many bulk_in urbs to do." ); + if (old_rdtodo + size < old_rdtodo) { + dbg("To many bulk_in urbs to do."); spin_unlock(&priv->lock); goto resubmit; } @@ -338,10 +347,10 @@ static void cyberjack_read_int_callback( struct urb *urb ) spin_unlock(&priv->lock); - if( !old_rdtodo ) { + if (!old_rdtodo) { port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if( result ) + if (result) err("%s - failed resubmitting read urb, error %d", __func__, result); dbg("%s - usb_submit_urb(read urb)", __func__); } @@ -355,7 +364,7 @@ resubmit: dbg("%s - usb_submit_urb(int urb)", __func__); } -static void cyberjack_read_bulk_callback (struct urb *urb) +static void cyberjack_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); @@ -367,14 +376,15 @@ static void cyberjack_read_bulk_callback (struct urb *urb) dbg("%s - port %d", __func__, port->number); - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); if (status) { dbg("%s - nonzero read bulk status received: %d", __func__, status); return; } - tty = port->tty; + tty = port->port.tty; if (!tty) { dbg("%s - ignoring since device not open\n", __func__); return; @@ -382,15 +392,16 @@ static void cyberjack_read_bulk_callback (struct urb *urb) if (urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + tty_flip_buffer_push(tty); } spin_lock(&priv->lock); /* Reduce urbs to do by one. */ - priv->rdtodo-=urb->actual_length; + priv->rdtodo -= urb->actual_length; /* Just to be sure */ - if ( priv->rdtodo<0 ) priv->rdtodo = 0; + if (priv->rdtodo < 0) + priv->rdtodo = 0; todo = priv->rdtodo; spin_unlock(&priv->lock); @@ -398,16 +409,17 @@ static void cyberjack_read_bulk_callback (struct urb *urb) dbg("%s - rdtodo: %d", __func__, todo); /* Continue to read if we have still urbs to do. */ - if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) { + if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) { port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", __func__, result); + err("%s - failed resubmitting read urb, error %d", + __func__, result); dbg("%s - usb_submit_urb(read urb)", __func__); } } -static void cyberjack_write_bulk_callback (struct urb *urb) +static void cyberjack_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); @@ -425,7 +437,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb) spin_lock(&priv->lock); /* only do something if we have more data to send */ - if( priv->wrfilled ) { + if (priv->wrfilled) { int length, blksize, result; dbg("%s - transmitting data (frame n)", __func__); @@ -433,37 +445,39 @@ static void cyberjack_write_bulk_callback (struct urb *urb) length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? port->bulk_out_size : (priv->wrfilled - priv->wrsent); - memcpy (port->write_urb->transfer_buffer, priv->wrbuf + priv->wrsent, - length ); - priv->wrsent+=length; + memcpy(port->write_urb->transfer_buffer, + priv->wrbuf + priv->wrsent, length); + priv->wrsent += length; /* set up our urb */ - usb_fill_bulk_urb(port->write_urb, port->serial->dev, + usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, length, - ((port->serial->type->write_bulk_callback) ? - port->serial->type->write_bulk_callback : - cyberjack_write_bulk_callback), + ((port->serial->type->write_bulk_callback) ? + port->serial->type->write_bulk_callback : + cyberjack_write_bulk_callback), port); /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", __func__, result); + err("%s - failed submitting write urb, error %d", + __func__, result); /* Throw away data. No better idea what to do with it. */ priv->wrfilled = 0; priv->wrsent = 0; goto exit; } - dbg("%s - priv->wrsent=%d", __func__,priv->wrsent); - dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled); + dbg("%s - priv->wrsent=%d", __func__, priv->wrsent); + dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled); blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; - if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) { + if (priv->wrsent >= priv->wrfilled || + priv->wrsent >= blksize) { dbg("%s - buffer cleaned", __func__); - memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); + memset(priv->wrbuf, 0, sizeof(priv->wrbuf)); priv->wrfilled = 0; priv->wrsent = 0; } @@ -474,14 +488,14 @@ exit: usb_serial_port_softint(port); } -static int __init cyberjack_init (void) +static int __init cyberjack_init(void) { int retval; retval = usb_serial_register(&cyberjack_device); if (retval) goto failed_usb_serial_register; retval = usb_register(&cyberjack_driver); - if (retval) + if (retval) goto failed_usb_register; info(DRIVER_VERSION " " DRIVER_AUTHOR); @@ -494,18 +508,18 @@ failed_usb_serial_register: return retval; } -static void __exit cyberjack_exit (void) +static void __exit cyberjack_exit(void) { - usb_deregister (&cyberjack_driver); - usb_serial_deregister (&cyberjack_device); + usb_deregister(&cyberjack_driver); + usb_serial_deregister(&cyberjack_device); } module_init(cyberjack_init); module_exit(cyberjack_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_VERSION( DRIVER_VERSION ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 0230d3c0888a..22837a3f2f89 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -2,7 +2,7 @@ * USB Cypress M8 driver * * Copyright (C) 2004 - * Lonnie Mendez (dignome@gmail.com) + * Lonnie Mendez (dignome@gmail.com) * Copyright (C) 2003,2004 * Neil Whelchel (koyama@firstlight.net) * @@ -11,19 +11,21 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * See http://geocities.com/i0xox0i for information on this driver and the * earthmate usb device. * * Lonnie Mendez <dignome@gmail.com> * 4-29-2005 - * Fixed problem where setting or retreiving the serial config would fail with - * EPIPE. Removed CRTS toggling so the driver behaves more like other usbserial - * adapters. Issued new interval of 1ms instead of the default 10ms. As a - * result, transfer speed has been substantially increased. From avg. 850bps to - * avg. 3300bps. initial termios has also been modified. Cleaned up code and - * formatting issues so it is more readable. Replaced the C++ style comments. + * Fixed problem where setting or retreiving the serial config would fail + * with EPIPE. Removed CRTS toggling so the driver behaves more like + * other usbserial adapters. Issued new interval of 1ms instead of the + * default 10ms. As a result, transfer speed has been substantially + * increased from avg. 850bps to avg. 3300bps. initial termios has also + * been modified. Cleaned up code and formatting issues so it is more + * readable. Replaced the C++ style comments. * * Lonnie Mendez <dignome@gmail.com> * 12-15-2004 @@ -42,10 +44,11 @@ * */ -/* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */ +/* Thanks to Neil Whelchel for writing the first cypress m8 implementation + for linux. */ /* Thanks to cypress for providing references for the hid reports. */ /* Thanks to Jiang Zhang for providing links and for general help. */ -/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */ +/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/ #include <linux/kernel.h> @@ -62,7 +65,7 @@ #include <linux/usb/serial.h> #include <linux/serial.h> #include <linux/delay.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "cypress_m8.h" @@ -112,7 +115,7 @@ static struct usb_device_id id_table_combined [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver cypress_driver = { .name = "cypress", @@ -146,11 +149,13 @@ struct cypress_private { __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */ enum packet_format pkt_fmt; /* format to use for packet send / receive */ int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */ - int baud_rate; /* stores current baud rate in integer form */ + int baud_rate; /* stores current baud rate in + integer form */ int isthrottled; /* if throttled, discard reads */ wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ char prev_status, diff_status; /* used for TIOCMIWAIT */ - /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ + /* we pass a pointer to this as the arguement sent to + cypress_set_termios old_termios */ struct ktermios tmp_termios; /* stores the old termios settings */ }; @@ -163,33 +168,41 @@ struct cypress_buf { }; /* function prototypes for the Cypress USB to serial device */ -static int cypress_earthmate_startup (struct usb_serial *serial); -static int cypress_hidcom_startup (struct usb_serial *serial); -static int cypress_ca42v2_startup (struct usb_serial *serial); -static void cypress_shutdown (struct usb_serial *serial); -static int cypress_open (struct usb_serial_port *port, struct file *filp); -static void cypress_close (struct usb_serial_port *port, struct file *filp); -static int cypress_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static void cypress_send (struct usb_serial_port *port); -static int cypress_write_room (struct usb_serial_port *port); -static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old); -static int cypress_tiocmget (struct usb_serial_port *port, struct file *file); -static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); -static int cypress_chars_in_buffer (struct usb_serial_port *port); -static void cypress_throttle (struct usb_serial_port *port); -static void cypress_unthrottle (struct usb_serial_port *port); -static void cypress_set_dead (struct usb_serial_port *port); -static void cypress_read_int_callback (struct urb *urb); -static void cypress_write_int_callback (struct urb *urb); +static int cypress_earthmate_startup(struct usb_serial *serial); +static int cypress_hidcom_startup(struct usb_serial *serial); +static int cypress_ca42v2_startup(struct usb_serial *serial); +static void cypress_shutdown(struct usb_serial *serial); +static int cypress_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void cypress_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static void cypress_send(struct usb_serial_port *port); +static int cypress_write_room(struct tty_struct *tty); +static int cypress_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void cypress_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static int cypress_tiocmget(struct tty_struct *tty, struct file *file); +static int cypress_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static int cypress_chars_in_buffer(struct tty_struct *tty); +static void cypress_throttle(struct tty_struct *tty); +static void cypress_unthrottle(struct tty_struct *tty); +static void cypress_set_dead(struct usb_serial_port *port); +static void cypress_read_int_callback(struct urb *urb); +static void cypress_write_int_callback(struct urb *urb); /* write buffer functions */ static struct cypress_buf *cypress_buf_alloc(unsigned int size); -static void cypress_buf_free(struct cypress_buf *cb); -static void cypress_buf_clear(struct cypress_buf *cb); -static unsigned int cypress_buf_data_avail(struct cypress_buf *cb); -static unsigned int cypress_buf_space_avail(struct cypress_buf *cb); -static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, unsigned int count); -static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count); +static void cypress_buf_free(struct cypress_buf *cb); +static void cypress_buf_clear(struct cypress_buf *cb); +static unsigned int cypress_buf_data_avail(struct cypress_buf *cb); +static unsigned int cypress_buf_space_avail(struct cypress_buf *cb); +static unsigned int cypress_buf_put(struct cypress_buf *cb, + const char *buf, unsigned int count); +static unsigned int cypress_buf_get(struct cypress_buf *cb, + char *buf, unsigned int count); static struct usb_serial_driver cypress_earthmate_device = { @@ -247,7 +260,7 @@ static struct usb_serial_driver cypress_hidcom_device = { static struct usb_serial_driver cypress_ca42v2_device = { .driver = { .owner = THIS_MODULE, - .name = "nokiaca42v2", + .name = "nokiaca42v2", }, .description = "Nokia CA-42 V2 Adapter", .usb_driver = &cypress_driver, @@ -322,8 +335,10 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) /* This function can either set or retrieve the current serial line settings */ -static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits, - int parity_enable, int parity_type, int reset, int cypress_request_type) +static int cypress_serial_control(struct tty_struct *tty, + struct usb_serial_port *port, speed_t baud_rate, int data_bits, + int stop_bits, int parity_enable, int parity_type, int reset, + int cypress_request_type) { int new_baudrate = 0, retval = 0, tries = 0; struct cypress_private *priv; @@ -331,111 +346,114 @@ static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_ra unsigned long flags; dbg("%s", __func__); - + priv = usb_get_serial_port_data(port); if (!priv->comm_is_ok) return -ENODEV; - switch(cypress_request_type) { - case CYPRESS_SET_CONFIG: + switch (cypress_request_type) { + case CYPRESS_SET_CONFIG: + new_baudrate = priv->baud_rate; + /* 0 means 'Hang up' so doesn't change the true bit rate */ + if (baud_rate == 0) new_baudrate = priv->baud_rate; - /* 0 means 'Hang up' so doesn't change the true bit rate */ - if (baud_rate == 0) - new_baudrate = priv->baud_rate; - /* Change of speed ? */ - else if (baud_rate != priv->baud_rate) { - dbg("%s - baud rate is changing", __func__); - retval = analyze_baud_rate(port, baud_rate); - if (retval >= 0) { - new_baudrate = retval; - dbg("%s - New baud rate set to %d", - __func__, new_baudrate); - } - } - dbg("%s - baud rate is being sent as %d", __func__, new_baudrate); - - memset(feature_buffer, 0, sizeof(feature_buffer)); - /* fill the feature_buffer with new configuration */ - *((u_int32_t *)feature_buffer) = new_baudrate; - - feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ - /* 1 bit gap */ - feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ - feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */ - feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */ - /* 1 bit gap */ - feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */ - - dbg("%s - device is being sent this feature report:", __func__); - dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1], - feature_buffer[2], feature_buffer[3], feature_buffer[4]); - - do { - retval = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - HID_REQ_SET_REPORT, - USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, - 0x0300, 0, feature_buffer, - sizeof(feature_buffer), 500); - - if (tries++ >= 3) - break; - - } while (retval != sizeof(feature_buffer) && - retval != -ENODEV); - - if (retval != sizeof(feature_buffer)) { - err("%s - failed sending serial line settings - %d", __func__, retval); - cypress_set_dead(port); - } else { - spin_lock_irqsave(&priv->lock, flags); - priv->baud_rate = new_baudrate; - priv->current_config = feature_buffer[4]; - spin_unlock_irqrestore(&priv->lock, flags); - /* If we asked for a speed change encode it */ - if (baud_rate) - tty_encode_baud_rate(port->tty, - new_baudrate, new_baudrate); - } - break; - case CYPRESS_GET_CONFIG: - if (priv->get_cfg_unsafe) { - /* Not implemented for this device, - and if we try to do it we're likely - to crash the hardware. */ - return -ENOTTY; - } - dbg("%s - retreiving serial line settings", __func__); - /* set initial values in feature buffer */ - memset(feature_buffer, 0, sizeof(feature_buffer)); - - do { - retval = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - HID_REQ_GET_REPORT, - USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, - 0x0300, 0, feature_buffer, - sizeof(feature_buffer), 500); - - if (tries++ >= 3) - break; - - } while (retval != sizeof(feature_buffer) && - retval != -ENODEV); - - if (retval != sizeof(feature_buffer)) { - err("%s - failed to retrieve serial line settings - %d", __func__, retval); - cypress_set_dead(port); - return retval; - } else { - spin_lock_irqsave(&priv->lock, flags); - - /* store the config in one byte, and later use bit masks to check values */ - priv->current_config = feature_buffer[4]; - priv->baud_rate = *((u_int32_t *)feature_buffer); - spin_unlock_irqrestore(&priv->lock, flags); + /* Change of speed ? */ + else if (baud_rate != priv->baud_rate) { + dbg("%s - baud rate is changing", __func__); + retval = analyze_baud_rate(port, baud_rate); + if (retval >= 0) { + new_baudrate = retval; + dbg("%s - New baud rate set to %d", + __func__, new_baudrate); } + } + dbg("%s - baud rate is being sent as %d", + __func__, new_baudrate); + + memset(feature_buffer, 0, sizeof(feature_buffer)); + /* fill the feature_buffer with new configuration */ + *((u_int32_t *)feature_buffer) = new_baudrate; + feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ + /* 1 bit gap */ + feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ + feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */ + feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */ + /* 1 bit gap */ + feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */ + + dbg("%s - device is being sent this feature report:", + __func__); + dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, + feature_buffer[0], feature_buffer[1], + feature_buffer[2], feature_buffer[3], + feature_buffer[4]); + + do { + retval = usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), + HID_REQ_SET_REPORT, + USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, + 0x0300, 0, feature_buffer, + sizeof(feature_buffer), 500); + + if (tries++ >= 3) + break; + + } while (retval != sizeof(feature_buffer) && + retval != -ENODEV); + + if (retval != sizeof(feature_buffer)) { + err("%s - failed sending serial line settings - %d", + __func__, retval); + cypress_set_dead(port); + } else { + spin_lock_irqsave(&priv->lock, flags); + priv->baud_rate = new_baudrate; + priv->current_config = feature_buffer[4]; + spin_unlock_irqrestore(&priv->lock, flags); + /* If we asked for a speed change encode it */ + if (baud_rate) + tty_encode_baud_rate(tty, + new_baudrate, new_baudrate); + } + break; + case CYPRESS_GET_CONFIG: + if (priv->get_cfg_unsafe) { + /* Not implemented for this device, + and if we try to do it we're likely + to crash the hardware. */ + return -ENOTTY; + } + dbg("%s - retreiving serial line settings", __func__); + /* set initial values in feature buffer */ + memset(feature_buffer, 0, sizeof(feature_buffer)); + + do { + retval = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + HID_REQ_GET_REPORT, + USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, + 0x0300, 0, feature_buffer, + sizeof(feature_buffer), 500); + + if (tries++ >= 3) + break; + } while (retval != sizeof(feature_buffer) + && retval != -ENODEV); + + if (retval != sizeof(feature_buffer)) { + err("%s - failed to retrieve serial line settings - %d", __func__, retval); + cypress_set_dead(port); + return retval; + } else { + spin_lock_irqsave(&priv->lock, flags); + /* store the config in one byte, and later + use bit masks to check values */ + priv->current_config = feature_buffer[4]; + priv->baud_rate = *((u_int32_t *)feature_buffer); + spin_unlock_irqrestore(&priv->lock, flags); + } } spin_lock_irqsave(&priv->lock, flags); ++priv->cmd_count; @@ -468,14 +486,14 @@ static void cypress_set_dead(struct usb_serial_port *port) *****************************************************************************/ -static int generic_startup (struct usb_serial *serial) +static int generic_startup(struct usb_serial *serial) { struct cypress_private *priv; struct usb_serial_port *port = serial->port[0]; dbg("%s - port %d", __func__, port->number); - priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -487,9 +505,9 @@ static int generic_startup (struct usb_serial *serial) return -ENOMEM; } init_waitqueue_head(&priv->delta_msr_wait); - - usb_reset_configuration (serial->dev); - + + usb_reset_configuration(serial->dev); + priv->cmd_ctrl = 0; priv->line_control = 0; priv->termios_initialized = 0; @@ -500,30 +518,30 @@ static int generic_startup (struct usb_serial *serial) small. Otherwise we can use the slightly more compact format. This is in accordance with the cypress_m8 serial converter app note. */ - if (port->interrupt_out_size > 9) { + if (port->interrupt_out_size > 9) priv->pkt_fmt = packet_format_1; - } else { + else priv->pkt_fmt = packet_format_2; - } + if (interval > 0) { priv->write_urb_interval = interval; priv->read_urb_interval = interval; dbg("%s - port %d read & write intervals forced to %d", - __func__,port->number,interval); + __func__, port->number, interval); } else { priv->write_urb_interval = port->interrupt_out_urb->interval; priv->read_urb_interval = port->interrupt_in_urb->interval; dbg("%s - port %d intervals: read=%d write=%d", - __func__,port->number, - priv->read_urb_interval,priv->write_urb_interval); + __func__, port->number, + priv->read_urb_interval, priv->write_urb_interval); } usb_set_serial_port_data(port, priv); - + return 0; } -static int cypress_earthmate_startup (struct usb_serial *serial) +static int cypress_earthmate_startup(struct usb_serial *serial) { struct cypress_private *priv; struct usb_serial_port *port = serial->port[0]; @@ -541,7 +559,8 @@ static int cypress_earthmate_startup (struct usb_serial *serial) /* All Earthmate devices use the separated-count packet format! Idiotic. */ priv->pkt_fmt = packet_format_1; - if (serial->dev->descriptor.idProduct != cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) { + if (serial->dev->descriptor.idProduct != + cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) { /* The old original USB Earthmate seemed able to handle GET_CONFIG requests; everything they've produced since that time crashes if this command is @@ -555,7 +574,7 @@ static int cypress_earthmate_startup (struct usb_serial *serial) } /* cypress_earthmate_startup */ -static int cypress_hidcom_startup (struct usb_serial *serial) +static int cypress_hidcom_startup(struct usb_serial *serial) { struct cypress_private *priv; @@ -569,12 +588,12 @@ static int cypress_hidcom_startup (struct usb_serial *serial) priv = usb_get_serial_port_data(serial->port[0]); priv->chiptype = CT_CYPHIDCOM; - + return 0; } /* cypress_hidcom_startup */ -static int cypress_ca42v2_startup (struct usb_serial *serial) +static int cypress_ca42v2_startup(struct usb_serial *serial) { struct cypress_private *priv; @@ -593,11 +612,11 @@ static int cypress_ca42v2_startup (struct usb_serial *serial) } /* cypress_ca42v2_startup */ -static void cypress_shutdown (struct usb_serial *serial) +static void cypress_shutdown(struct usb_serial *serial) { struct cypress_private *priv; - dbg ("%s - port %d", __func__, serial->port[0]->number); + dbg("%s - port %d", __func__, serial->port[0]->number); /* all open ports are closed at this point */ @@ -611,7 +630,8 @@ static void cypress_shutdown (struct usb_serial *serial) } -static int cypress_open (struct usb_serial_port *port, struct file *filp) +static int cypress_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct cypress_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; @@ -636,37 +656,44 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp) spin_unlock_irqrestore(&priv->lock, flags); /* setting to zero could cause data loss */ - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; /* raise both lines and set termios */ spin_lock_irqsave(&priv->lock, flags); priv->line_control = CONTROL_DTR | CONTROL_RTS; priv->cmd_ctrl = 1; spin_unlock_irqrestore(&priv->lock, flags); - result = cypress_write(port, NULL, 0); + result = cypress_write(tty, port, NULL, 0); if (result) { - dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed setting the control lines - error %d\n", + __func__, result); return result; } else dbg("%s - success setting the control lines", __func__); - cypress_set_termios(port, &priv->tmp_termios); + if (tty) + cypress_set_termios(tty, port, &priv->tmp_termios); /* setup the port and start reading from the device */ - if(!port->interrupt_in_urb){ + if (!port->interrupt_in_urb) { err("%s - interrupt_in_urb is empty!", __func__); - return(-1); + return -1; } usb_fill_int_urb(port->interrupt_in_urb, serial->dev, usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), - port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, + port->interrupt_in_urb->transfer_buffer, + port->interrupt_in_urb->transfer_buffer_length, cypress_read_int_callback, port, priv->read_urb_interval); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - if (result){ - dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); + if (result) { + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); cypress_set_dead(port); } @@ -674,7 +701,8 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp) } /* cypress_open */ -static void cypress_close(struct usb_serial_port *port, struct file * filp) +static void cypress_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct cypress_private *priv = usb_get_serial_port_data(port); unsigned int c_cflag; @@ -688,7 +716,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) spin_lock_irq(&priv->lock); timeout = CYPRESS_CLOSING_WAIT; init_waitqueue_entry(&wait, current); - add_wait_queue(&port->tty->write_wait, &wait); + add_wait_queue(&tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (cypress_buf_data_avail(priv->buf) == 0 @@ -701,7 +729,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) spin_lock_irq(&priv->lock); } set_current_state(TASK_RUNNING); - remove_wait_queue(&port->tty->write_wait, &wait); + remove_wait_queue(&tty->write_wait, &wait); /* clear out any remaining data in the buffer */ cypress_buf_clear(priv->buf); spin_unlock_irq(&priv->lock); @@ -713,19 +741,21 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) return; } /* wait for characters to drain from device */ - bps = tty_get_baud_rate(port->tty); - if (bps > 1200) - timeout = max((HZ*2560)/bps,HZ/10); - else - timeout = 2*HZ; - schedule_timeout_interruptible(timeout); + if (tty) { + bps = tty_get_baud_rate(tty); + if (bps > 1200) + timeout = max((HZ * 2560) / bps, HZ / 10); + else + timeout = 2 * HZ; + schedule_timeout_interruptible(timeout); + } dbg("%s - stopping urbs", __func__); - usb_kill_urb (port->interrupt_in_urb); - usb_kill_urb (port->interrupt_out_urb); + usb_kill_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_out_urb); - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; + if (tty) { + c_cflag = tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop dtr and rts */ priv = usb_get_serial_port_data(port); @@ -733,22 +763,23 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) priv->line_control = 0; priv->cmd_ctrl = 1; spin_unlock_irq(&priv->lock); - cypress_write(port, NULL, 0); + cypress_write(tty, port, NULL, 0); } } if (stats) - dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", - priv->bytes_in, priv->bytes_out, priv->cmd_count); + dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", + priv->bytes_in, priv->bytes_out, priv->cmd_count); mutex_unlock(&port->serial->disc_mutex); } /* cypress_close */ -static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count) +static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - + dbg("%s - port %d, %d bytes", __func__, port->number, count); /* line control commands, which need to be executed immediately, @@ -758,10 +789,10 @@ static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, count = 0; goto finish; } - + if (!count) return count; - + spin_lock_irqsave(&priv->lock, flags); count = cypress_buf_put(priv->buf, buf, count); spin_unlock_irqrestore(&priv->lock, flags); @@ -778,13 +809,14 @@ static void cypress_send(struct usb_serial_port *port) int count = 0, result, offset, actual_size; struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - + if (!priv->comm_is_ok) return; dbg("%s - port %d", __func__, port->number); - dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size); - + dbg("%s - interrupt out size is %d", __func__, + port->interrupt_out_size); + spin_lock_irqsave(&priv->lock, flags); if (priv->write_urb_in_use) { dbg("%s - can't write, urb in use", __func__); @@ -794,7 +826,8 @@ static void cypress_send(struct usb_serial_port *port) spin_unlock_irqrestore(&priv->lock, flags); /* clear buffer */ - memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size); + memset(port->interrupt_out_urb->transfer_buffer, 0, + port->interrupt_out_size); spin_lock_irqsave(&priv->lock, flags); switch (priv->pkt_fmt) { @@ -825,9 +858,8 @@ static void cypress_send(struct usb_serial_port *port) count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset], port->interrupt_out_size-offset); - if (count == 0) { + if (count == 0) return; - } switch (priv->pkt_fmt) { default: @@ -851,26 +883,29 @@ send: actual_size = count + (priv->pkt_fmt == packet_format_1 ? 2 : 1); - usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size, - port->interrupt_out_urb->transfer_buffer); + usb_serial_debug_data(debug, &port->dev, __func__, + port->interrupt_out_size, + port->interrupt_out_urb->transfer_buffer); usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev, usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), port->interrupt_out_buffer, port->interrupt_out_size, cypress_write_int_callback, port, priv->write_urb_interval); - result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC); + result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, - result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); priv->write_urb_in_use = 0; cypress_set_dead(port); } spin_lock_irqsave(&priv->lock, flags); - if (priv->cmd_ctrl) { + if (priv->cmd_ctrl) priv->cmd_ctrl = 0; - } - priv->bytes_out += count; /* do not count the line control and size bytes */ + + /* do not count the line control and size bytes */ + priv->bytes_out += count; spin_unlock_irqrestore(&priv->lock, flags); usb_serial_port_softint(port); @@ -878,8 +913,9 @@ send: /* returns how much space is available in the soft buffer */ -static int cypress_write_room(struct usb_serial_port *port) +static int cypress_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); int room = 0; unsigned long flags; @@ -895,13 +931,14 @@ static int cypress_write_room(struct usb_serial_port *port) } -static int cypress_tiocmget (struct usb_serial_port *port, struct file *file) +static int cypress_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); __u8 status, control; unsigned int result = 0; unsigned long flags; - + dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); @@ -922,12 +959,13 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file) } -static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, +static int cypress_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - + dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); @@ -942,63 +980,60 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, priv->cmd_ctrl = 1; spin_unlock_irqrestore(&priv->lock, flags); - return cypress_write(port, NULL, 0); + return cypress_write(tty, port, NULL, 0); } -static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +static int cypress_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); switch (cmd) { - /* This code comes from drivers/char/serial.c and ftdi_sio.c */ - case TIOCMIWAIT: - while (priv != NULL) { - interruptible_sleep_on(&priv->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - else { - char diff = priv->diff_status; - - if (diff == 0) { - return -EIO; /* no change => error */ - } - - /* consume all events */ - priv->diff_status = 0; - - /* return 0 if caller wanted to know about these bits */ - if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) || - ((arg & TIOCM_DSR) && (diff & UART_DSR)) || - ((arg & TIOCM_CD) && (diff & UART_CD)) || - ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) { - return 0; - } - /* otherwise caller can't care less about what happened, - * and so we continue to wait for more events. - */ - } + /* This code comes from drivers/char/serial.c and ftdi_sio.c */ + case TIOCMIWAIT: + while (priv != NULL) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + else { + char diff = priv->diff_status; + if (diff == 0) + return -EIO; /* no change => error */ + + /* consume all events */ + priv->diff_status = 0; + + /* return 0 if caller wanted to know about + these bits */ + if (((arg & TIOCM_RNG) && (diff & UART_RI)) || + ((arg & TIOCM_DSR) && (diff & UART_DSR)) || + ((arg & TIOCM_CD) && (diff & UART_CD)) || + ((arg & TIOCM_CTS) && (diff & UART_CTS))) + return 0; + /* otherwise caller can't care less about what + * happened, and so we continue to wait for + * more events. + */ } - return 0; - break; - default: - break; + } + return 0; + default: + break; } - dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd); - return -ENOIOCTLCMD; } /* cypress_ioctl */ -static void cypress_set_termios (struct usb_serial_port *port, - struct ktermios *old_termios) +static void cypress_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct cypress_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; int data_bits, stop_bits, parity_type, parity_enable; unsigned cflag, iflag; unsigned long flags; @@ -1007,8 +1042,6 @@ static void cypress_set_termios (struct usb_serial_port *port, dbg("%s - port %d", __func__, port->number); - tty = port->tty; - spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { if (priv->chiptype == CT_EARTHMATE) { @@ -1060,28 +1093,24 @@ static void cypress_set_termios (struct usb_serial_port *port, } else parity_enable = parity_type = 0; - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - data_bits = 0; - break; - case CS6: - data_bits = 1; - break; - case CS7: - data_bits = 2; - break; - case CS8: - data_bits = 3; - break; - default: - err("%s - CSIZE was set, but not CS5-CS8", - __func__); - data_bits = 3; - } - } else + switch (cflag & CSIZE) { + case CS5: + data_bits = 0; + break; + case CS6: + data_bits = 1; + break; + case CS7: + data_bits = 2; + break; + case CS8: data_bits = 3; - + break; + default: + err("%s - CSIZE was set, but not CS5-CS8", + __func__); + data_bits = 3; + } spin_lock_irqsave(&priv->lock, flags); oldlines = priv->line_control; if ((cflag & CBAUD) == B0) { @@ -1096,19 +1125,21 @@ static void cypress_set_termios (struct usb_serial_port *port, "%d data_bits (+5)", __func__, stop_bits, parity_enable, parity_type, data_bits); - cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits, - parity_enable, parity_type, 0, CYPRESS_SET_CONFIG); + cypress_serial_control(tty, port, tty_get_baud_rate(tty), + data_bits, stop_bits, + parity_enable, parity_type, + 0, CYPRESS_SET_CONFIG); /* we perform a CYPRESS_GET_CONFIG so that the current settings are * filled into the private structure this should confirm that all is * working if it returns what we just set */ - cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG); + cypress_serial_control(tty, port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG); /* Here we can define custom tty settings for devices; the main tty * termios flag base comes from empeg.c */ spin_lock_irqsave(&priv->lock, flags); - if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) { + if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) { dbg("Using custom termios settings for a baud rate of " "4800bps."); /* define custom termios settings for NMEA protocol */ @@ -1142,20 +1173,21 @@ static void cypress_set_termios (struct usb_serial_port *port, /* if necessary, set lines */ if (linechange) { priv->cmd_ctrl = 1; - cypress_write(port, NULL, 0); + cypress_write(tty, port, NULL, 0); } } /* cypress_set_termios */ /* returns amount of data still left in soft buffer */ -static int cypress_chars_in_buffer(struct usb_serial_port *port) +static int cypress_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; dbg("%s - port %d", __func__, port->number); - + spin_lock_irqsave(&priv->lock, flags); chars = cypress_buf_data_avail(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); @@ -1165,8 +1197,9 @@ static int cypress_chars_in_buffer(struct usb_serial_port *port) } -static void cypress_throttle (struct usb_serial_port *port) +static void cypress_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -1178,8 +1211,9 @@ static void cypress_throttle (struct usb_serial_port *port) } -static void cypress_unthrottle (struct usb_serial_port *port) +static void cypress_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); int actually_throttled, result; unsigned long flags; @@ -1232,12 +1266,13 @@ static void cypress_read_int_callback(struct urb *urb) /* precursor to disconnect so just go away */ return; case -EPIPE: - usb_clear_halt(port->serial->dev,0x81); + usb_clear_halt(port->serial->dev, 0x81); break; default: /* something ugly is going on... */ - dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n", - __func__, status); + dev_err(&urb->dev->dev, + "%s - unexpected nonzero read status received: %d\n", + __func__, status); cypress_set_dead(port); return; } @@ -1251,7 +1286,7 @@ static void cypress_read_int_callback(struct urb *urb) } spin_unlock_irqrestore(&priv->lock, flags); - tty = port->tty; + tty = port->port.tty; if (!tty) { dbg("%s - bad tty pointer - exiting", __func__); return; @@ -1285,8 +1320,8 @@ static void cypress_read_int_callback(struct urb *urb) goto continue_read; } - usb_serial_debug_data (debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); spin_lock_irqsave(&priv->lock, flags); /* check to see if status has changed */ @@ -1327,7 +1362,7 @@ static void cypress_read_int_callback(struct urb *urb) data[i]); tty_insert_flip_char(tty, data[i], tty_flag); } - tty_flip_buffer_push(port->tty); + tty_flip_buffer_push(port->port.tty); } spin_lock_irqsave(&priv->lock, flags); @@ -1339,13 +1374,14 @@ continue_read: /* Continue trying to always read... unless the port has closed. */ - if (port->open_count > 0 && priv->comm_is_ok) { + if (port->port.count > 0 && priv->comm_is_ok) { usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress), port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, - cypress_read_int_callback, port, priv->read_urb_interval); + cypress_read_int_callback, port, + priv->read_urb_interval); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) { dev_err(&urb->dev->dev, "%s - failed resubmitting " @@ -1369,42 +1405,43 @@ static void cypress_write_int_callback(struct urb *urb) dbg("%s - port %d", __func__, port->number); switch (status) { - case 0: - /* success */ + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, status); + priv->write_urb_in_use = 0; + return; + case -EPIPE: /* no break needed; clear halt and resubmit */ + if (!priv->comm_is_ok) break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); - priv->write_urb_in_use = 0; + usb_clear_halt(port->serial->dev, 0x02); + /* error in the urb, so we have to resubmit it */ + dbg("%s - nonzero write bulk status received: %d", + __func__, status); + port->interrupt_out_urb->transfer_buffer_length = 1; + port->interrupt_out_urb->dev = port->serial->dev; + result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); + if (!result) return; - case -EPIPE: /* no break needed; clear halt and resubmit */ - if (!priv->comm_is_ok) - break; - usb_clear_halt(port->serial->dev, 0x02); - /* error in the urb, so we have to resubmit it */ - dbg("%s - nonzero write bulk status received: %d", - __func__, status); - port->interrupt_out_urb->transfer_buffer_length = 1; - port->interrupt_out_urb->dev = port->serial->dev; - result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); - if (!result) - return; - dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", - __func__, result); - cypress_set_dead(port); - break; - default: - dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n", - __func__, status); - cypress_set_dead(port); - break; + dev_err(&urb->dev->dev, + "%s - failed resubmitting write urb, error %d\n", + __func__, result); + cypress_set_dead(port); + break; + default: + dev_err(&urb->dev->dev, + "%s - unexpected nonzero write status received: %d\n", + __func__, status); + cypress_set_dead(port); + break; } - priv->write_urb_in_use = 0; - + /* send any buffered data */ cypress_send(port); } @@ -1486,7 +1523,8 @@ static void cypress_buf_clear(struct cypress_buf *cb) static unsigned int cypress_buf_data_avail(struct cypress_buf *cb) { if (cb != NULL) - return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size); + return (cb->buf_size + cb->buf_put - cb->buf_get) + % cb->buf_size; else return 0; } @@ -1502,7 +1540,8 @@ static unsigned int cypress_buf_data_avail(struct cypress_buf *cb) static unsigned int cypress_buf_space_avail(struct cypress_buf *cb) { if (cb != NULL) - return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size); + return (cb->buf_size + cb->buf_get - cb->buf_put - 1) + % cb->buf_size; else return 0; } @@ -1602,9 +1641,9 @@ static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, static int __init cypress_init(void) { int retval; - + dbg("%s", __func__); - + retval = usb_serial_register(&cypress_earthmate_device); if (retval) goto failed_em_register; @@ -1632,23 +1671,23 @@ failed_em_register: } -static void __exit cypress_exit (void) +static void __exit cypress_exit(void) { dbg("%s", __func__); - usb_deregister (&cypress_driver); - usb_serial_deregister (&cypress_earthmate_device); - usb_serial_deregister (&cypress_hidcom_device); - usb_serial_deregister (&cypress_ca42v2_device); + usb_deregister(&cypress_driver); + usb_serial_deregister(&cypress_earthmate_device); + usb_serial_deregister(&cypress_hidcom_device); + usb_serial_deregister(&cypress_ca42v2_device); } module_init(cypress_init); module_exit(cypress_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_VERSION( DRIVER_VERSION ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h index 0388065bb794..e772b01ac3ac 100644 --- a/drivers/usb/serial/cypress_m8.h +++ b/drivers/usb/serial/cypress_m8.h @@ -54,7 +54,7 @@ #define UART_DSR 0x20 /* data set ready - flow control - device to host */ #define CONTROL_RTS 0x10 /* request to send - flow control - host to device */ #define UART_CTS 0x10 /* clear to send - flow control - device to host */ -#define UART_RI 0x10 /* ring indicator - modem - device to host */ +#define UART_RI 0x10 /* ring indicator - modem - device to host */ #define UART_CD 0x40 /* carrier detect - modem - device to host */ #define CYP_ERROR 0x08 /* received from input report - device to host */ /* Note - the below has nothing to to with the "feature report" reset */ diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 04a56f300ea6..240aad1acaab 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -15,7 +15,7 @@ * Al Borchers (borchers@steinerpoint.com) * * (12/03/2001) gkh -* switched to using port->open_count instead of private version. +* switched to using port->port.count instead of private version. * Removed port->active * * (04/08/2001) gb @@ -229,8 +229,6 @@ * in case a wake up is lost. * - Following Documentation/DocBook/kernel-locking.pdf no spin locks * are held when calling copy_to/from_user or printk. -* -* $Id: digi_acceleport.c,v 1.80.1.2 2000/11/02 05:45:08 root Exp $ */ #include <linux/kernel.h> @@ -243,7 +241,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/workqueue.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/wait.h> #include <linux/usb/serial.h> @@ -443,22 +441,23 @@ static int digi_set_modem_signals(struct usb_serial_port *port, unsigned int modem_signals, int interruptible); static int digi_transmit_idle(struct usb_serial_port *port, unsigned long timeout); -static void digi_rx_throttle (struct usb_serial_port *port); -static void digi_rx_unthrottle (struct usb_serial_port *port); -static void digi_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios); -static void digi_break_ctl(struct usb_serial_port *port, int break_state); -static int digi_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg); -static int digi_tiocmget(struct usb_serial_port *port, struct file *file); -static int digi_tiocmset(struct usb_serial_port *port, struct file *file, +static void digi_rx_throttle(struct tty_struct *tty); +static void digi_rx_unthrottle(struct tty_struct *tty); +static void digi_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios); +static void digi_break_ctl(struct tty_struct *tty, int break_state); +static int digi_tiocmget(struct tty_struct *tty, struct file *file); +static int digi_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); -static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count); +static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); static void digi_write_bulk_callback(struct urb *urb); -static int digi_write_room(struct usb_serial_port *port); -static int digi_chars_in_buffer(struct usb_serial_port *port); -static int digi_open(struct usb_serial_port *port, struct file *filp); -static void digi_close(struct usb_serial_port *port, struct file *filp); +static int digi_write_room(struct tty_struct *tty); +static int digi_chars_in_buffer(struct tty_struct *tty); +static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); static void digi_shutdown(struct usb_serial *serial); @@ -487,7 +486,7 @@ static struct usb_device_id id_table_4 [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver digi_driver = { .name = "digi_acceleport", @@ -518,7 +517,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .chars_in_buffer = digi_chars_in_buffer, .throttle = digi_rx_throttle, .unthrottle = digi_rx_unthrottle, - .ioctl = digi_ioctl, .set_termios = digi_set_termios, .break_ctl = digi_break_ctl, .tiocmget = digi_tiocmget, @@ -545,7 +543,6 @@ static struct usb_serial_driver digi_acceleport_4_device = { .chars_in_buffer = digi_chars_in_buffer, .throttle = digi_rx_throttle, .unthrottle = digi_rx_unthrottle, - .ioctl = digi_ioctl, .set_termios = digi_set_termios, .break_ctl = digi_break_ctl, .tiocmget = digi_tiocmget, @@ -558,21 +555,22 @@ static struct usb_serial_driver digi_acceleport_4_device = { /* Functions */ /* -* Cond Wait Interruptible Timeout Irqrestore -* -* Do spin_unlock_irqrestore and interruptible_sleep_on_timeout -* so that wake ups are not lost if they occur between the unlock -* and the sleep. In other words, spin_unlock_irqrestore and -* interruptible_sleep_on_timeout are "atomic" with respect to -* wake ups. This is used to implement condition variables. -* -* interruptible_sleep_on_timeout is deprecated and has been replaced -* with the equivalent code. -*/ + * Cond Wait Interruptible Timeout Irqrestore + * + * Do spin_unlock_irqrestore and interruptible_sleep_on_timeout + * so that wake ups are not lost if they occur between the unlock + * and the sleep. In other words, spin_unlock_irqrestore and + * interruptible_sleep_on_timeout are "atomic" with respect to + * wake ups. This is used to implement condition variables. + * + * interruptible_sleep_on_timeout is deprecated and has been replaced + * with the equivalent code. + */ static long cond_wait_interruptible_timeout_irqrestore( wait_queue_head_t *q, long timeout, spinlock_t *lock, unsigned long flags) +__releases(lock) { DEFINE_WAIT(wait); @@ -586,15 +584,16 @@ static long cond_wait_interruptible_timeout_irqrestore( /* -* Digi Wakeup Write -* -* Wake up port, line discipline, and tty processes sleeping -* on writes. -*/ + * Digi Wakeup Write + * + * Wake up port, line discipline, and tty processes sleeping + * on writes. + */ static void digi_wakeup_write_lock(struct work_struct *work) { - struct digi_port *priv = container_of(work, struct digi_port, dp_wakeup_work); + struct digi_port *priv = + container_of(work, struct digi_port, dp_wakeup_work); struct usb_serial_port *port = priv->dp_port; unsigned long flags; @@ -605,20 +604,20 @@ static void digi_wakeup_write_lock(struct work_struct *work) static void digi_wakeup_write(struct usb_serial_port *port) { - tty_wakeup(port->tty); + tty_wakeup(port->port.tty); } /* -* Digi Write OOB Command -* -* Write commands on the out of band port. Commands are 4 -* bytes each, multiple commands can be sent at once, and -* no command will be split across USB packets. Returns 0 -* if successful, -EINTR if interrupted while sleeping and -* the interruptible flag is true, or a negative error -* returned by usb_submit_urb. -*/ + * Digi Write OOB Command + * + * Write commands on the out of band port. Commands are 4 + * bytes each, multiple commands can be sent at once, and + * no command will be split across USB packets. Returns 0 + * if successful, -EINTR if interrupted while sleeping and + * the interruptible flag is true, or a negative error + * returned by usb_submit_urb. + */ static int digi_write_oob_command(struct usb_serial_port *port, unsigned char *buf, int count, int interruptible) @@ -633,8 +632,8 @@ static int digi_write_oob_command(struct usb_serial_port *port, dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count); spin_lock_irqsave(&oob_priv->dp_port_lock, flags); - while(count > 0) { - while(oob_port->write_urb->status == -EINPROGRESS + while (count > 0) { + while (oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) { cond_wait_interruptible_timeout_irqrestore( &oob_port->write_wait, DIGI_RETRY_TIMEOUT, @@ -651,7 +650,8 @@ static int digi_write_oob_command(struct usb_serial_port *port, memcpy(oob_port->write_urb->transfer_buffer, buf, len); oob_port->write_urb->transfer_buffer_length = len; oob_port->write_urb->dev = port->serial->dev; - if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) { + ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC); + if (ret == 0) { oob_priv->dp_write_urb_in_use = 1; count -= len; buf += len; @@ -666,16 +666,16 @@ static int digi_write_oob_command(struct usb_serial_port *port, /* -* Digi Write In Band Command -* -* Write commands on the given port. Commands are 4 -* bytes each, multiple commands can be sent at once, and -* no command will be split across USB packets. If timeout -* is non-zero, write in band command will return after -* waiting unsuccessfully for the URB status to clear for -* timeout ticks. Returns 0 if successful, or a negative -* error returned by digi_write. -*/ + * Digi Write In Band Command + * + * Write commands on the given port. Commands are 4 + * bytes each, multiple commands can be sent at once, and + * no command will be split across USB packets. If timeout + * is non-zero, write in band command will return after + * waiting unsuccessfully for the URB status to clear for + * timeout ticks. Returns 0 if successful, or a negative + * error returned by digi_write. + */ static int digi_write_inb_command(struct usb_serial_port *port, unsigned char *buf, int count, unsigned long timeout) @@ -695,9 +695,10 @@ static int digi_write_inb_command(struct usb_serial_port *port, timeout = ULONG_MAX; spin_lock_irqsave(&priv->dp_port_lock, flags); - while(count > 0 && ret == 0) { - while((port->write_urb->status == -EINPROGRESS - || priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) { + while (count > 0 && ret == 0) { + while ((port->write_urb->status == -EINPROGRESS + || priv->dp_write_urb_in_use) + && time_before(jiffies, timeout)) { cond_wait_interruptible_timeout_irqrestore( &port->write_wait, DIGI_RETRY_TIMEOUT, &priv->dp_port_lock, flags); @@ -728,7 +729,8 @@ static int digi_write_inb_command(struct usb_serial_port *port, } port->write_urb->dev = port->serial->dev; - if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) { + ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); + if (ret == 0) { priv->dp_write_urb_in_use = 1; priv->dp_out_buf_len = 0; count -= len; @@ -746,14 +748,14 @@ static int digi_write_inb_command(struct usb_serial_port *port, /* -* Digi Set Modem Signals -* -* Sets or clears DTR and RTS on the port, according to the -* modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags -* for the modem_signals argument. Returns 0 if successful, -* -EINTR if interrupted while sleeping, or a non-zero error -* returned by usb_submit_urb. -*/ + * Digi Set Modem Signals + * + * Sets or clears DTR and RTS on the port, according to the + * modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags + * for the modem_signals argument. Returns 0 if successful, + * -EINTR if interrupted while sleeping, or a non-zero error + * returned by usb_submit_urb. + */ static int digi_set_modem_signals(struct usb_serial_port *port, unsigned int modem_signals, int interruptible) @@ -761,7 +763,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port, int ret; struct digi_port *port_priv = usb_get_serial_port_data(port); - struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port; + struct usb_serial_port *oob_port = (struct usb_serial_port *) ((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port; struct digi_port *oob_priv = usb_get_serial_port_data(oob_port); unsigned char *data = oob_port->write_urb->transfer_buffer; unsigned long flags = 0; @@ -773,7 +775,8 @@ static int digi_set_modem_signals(struct usb_serial_port *port, spin_lock_irqsave(&oob_priv->dp_port_lock, flags); spin_lock(&port_priv->dp_port_lock); - while(oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) { + while (oob_port->write_urb->status == -EINPROGRESS || + oob_priv->dp_write_urb_in_use) { spin_unlock(&port_priv->dp_port_lock); cond_wait_interruptible_timeout_irqrestore( &oob_port->write_wait, DIGI_RETRY_TIMEOUT, @@ -785,17 +788,20 @@ static int digi_set_modem_signals(struct usb_serial_port *port, } data[0] = DIGI_CMD_SET_DTR_SIGNAL; data[1] = port_priv->dp_port_num; - data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE; + data[2] = (modem_signals & TIOCM_DTR) ? + DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE; data[3] = 0; data[4] = DIGI_CMD_SET_RTS_SIGNAL; data[5] = port_priv->dp_port_num; - data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE; + data[6] = (modem_signals & TIOCM_RTS) ? + DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE; data[7] = 0; oob_port->write_urb->transfer_buffer_length = 8; oob_port->write_urb->dev = port->serial->dev; - if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) { + ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC); + if (ret == 0) { oob_priv->dp_write_urb_in_use = 1; port_priv->dp_modem_signals = (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) @@ -809,16 +815,16 @@ static int digi_set_modem_signals(struct usb_serial_port *port, } /* -* Digi Transmit Idle -* -* Digi transmit idle waits, up to timeout ticks, for the transmitter -* to go idle. It returns 0 if successful or a negative error. -* -* There are race conditions here if more than one process is calling -* digi_transmit_idle on the same port at the same time. However, this -* is only called from close, and only one process can be in close on a -* port at a time, so its ok. -*/ + * Digi Transmit Idle + * + * Digi transmit idle waits, up to timeout ticks, for the transmitter + * to go idle. It returns 0 if successful or a negative error. + * + * There are race conditions here if more than one process is calling + * digi_transmit_idle on the same port at the same time. However, this + * is only called from close, and only one process can be in close on a + * port at a time, so its ok. + */ static int digi_transmit_idle(struct usb_serial_port *port, unsigned long timeout) @@ -837,12 +843,13 @@ static int digi_transmit_idle(struct usb_serial_port *port, timeout += jiffies; - if ((ret = digi_write_inb_command(port, buf, 2, timeout - jiffies)) != 0) + ret = digi_write_inb_command(port, buf, 2, timeout - jiffies); + if (ret != 0) return ret; spin_lock_irqsave(&priv->dp_port_lock, flags); - while(time_before(jiffies, timeout) && !priv->dp_transmit_idle) { + while (time_before(jiffies, timeout) && !priv->dp_transmit_idle) { cond_wait_interruptible_timeout_irqrestore( &priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT, &priv->dp_port_lock, flags); @@ -857,9 +864,10 @@ static int digi_transmit_idle(struct usb_serial_port *port, } -static void digi_rx_throttle(struct usb_serial_port *port) +static void digi_rx_throttle(struct tty_struct *tty) { unsigned long flags; + struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); @@ -873,10 +881,11 @@ static void digi_rx_throttle(struct usb_serial_port *port) } -static void digi_rx_unthrottle(struct usb_serial_port *port) +static void digi_rx_unthrottle(struct tty_struct *tty) { int ret = 0; unsigned long flags; + struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num); @@ -901,26 +910,25 @@ static void digi_rx_unthrottle(struct usb_serial_port *port) } -static void digi_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) +static void digi_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { - struct digi_port *priv = usb_get_serial_port_data(port); - struct tty_struct *tty = port->tty; unsigned int iflag = tty->termios->c_iflag; unsigned int cflag = tty->termios->c_cflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int old_cflag = old_termios->c_cflag; unsigned char buf[32]; unsigned int modem_signals; - int arg,ret; + int arg, ret; int i = 0; speed_t baud; dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag); /* set baud rate */ - if ((baud = tty_get_baud_rate(tty)) != tty_termios_baud_rate(old_termios)) { + baud = tty_get_baud_rate(tty); + if (baud != tty_termios_baud_rate(old_termios)) { arg = -1; /* reassert DTR and (maybe) RTS on transition from B0 */ @@ -934,30 +942,30 @@ static void digi_set_termios(struct usb_serial_port *port, digi_set_modem_signals(port, modem_signals, 1); } switch (baud) { - /* drop DTR and RTS on transition to B0 */ - case 0: digi_set_modem_signals(port, 0, 1); break; - case 50: arg = DIGI_BAUD_50; break; - case 75: arg = DIGI_BAUD_75; break; - case 110: arg = DIGI_BAUD_110; break; - case 150: arg = DIGI_BAUD_150; break; - case 200: arg = DIGI_BAUD_200; break; - case 300: arg = DIGI_BAUD_300; break; - case 600: arg = DIGI_BAUD_600; break; - case 1200: arg = DIGI_BAUD_1200; break; - case 1800: arg = DIGI_BAUD_1800; break; - case 2400: arg = DIGI_BAUD_2400; break; - case 4800: arg = DIGI_BAUD_4800; break; - case 9600: arg = DIGI_BAUD_9600; break; - case 19200: arg = DIGI_BAUD_19200; break; - case 38400: arg = DIGI_BAUD_38400; break; - case 57600: arg = DIGI_BAUD_57600; break; - case 115200: arg = DIGI_BAUD_115200; break; - case 230400: arg = DIGI_BAUD_230400; break; - case 460800: arg = DIGI_BAUD_460800; break; - default: - arg = DIGI_BAUD_9600; - baud = 9600; - break; + /* drop DTR and RTS on transition to B0 */ + case 0: digi_set_modem_signals(port, 0, 1); break; + case 50: arg = DIGI_BAUD_50; break; + case 75: arg = DIGI_BAUD_75; break; + case 110: arg = DIGI_BAUD_110; break; + case 150: arg = DIGI_BAUD_150; break; + case 200: arg = DIGI_BAUD_200; break; + case 300: arg = DIGI_BAUD_300; break; + case 600: arg = DIGI_BAUD_600; break; + case 1200: arg = DIGI_BAUD_1200; break; + case 1800: arg = DIGI_BAUD_1800; break; + case 2400: arg = DIGI_BAUD_2400; break; + case 4800: arg = DIGI_BAUD_4800; break; + case 9600: arg = DIGI_BAUD_9600; break; + case 19200: arg = DIGI_BAUD_19200; break; + case 38400: arg = DIGI_BAUD_38400; break; + case 57600: arg = DIGI_BAUD_57600; break; + case 115200: arg = DIGI_BAUD_115200; break; + case 230400: arg = DIGI_BAUD_230400; break; + case 460800: arg = DIGI_BAUD_460800; break; + default: + arg = DIGI_BAUD_9600; + baud = 9600; + break; } if (arg != -1) { buf[i++] = DIGI_CMD_SET_BAUD_RATE; @@ -1083,14 +1091,16 @@ static void digi_set_termios(struct usb_serial_port *port, buf[i++] = arg; buf[i++] = 0; } - if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0) + ret = digi_write_oob_command(port, buf, i, 1); + if (ret != 0) dbg("digi_set_termios: write oob failed, ret=%d", ret); tty_encode_baud_rate(tty, baud, baud); } -static void digi_break_ctl(struct usb_serial_port *port, int break_state) +static void digi_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; unsigned char buf[4]; buf[0] = DIGI_CMD_BREAK_CONTROL; @@ -1101,8 +1111,9 @@ static void digi_break_ctl(struct usb_serial_port *port, int break_state) } -static int digi_tiocmget(struct usb_serial_port *port, struct file *file) +static int digi_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); unsigned int val; unsigned long flags; @@ -1116,9 +1127,10 @@ static int digi_tiocmget(struct usb_serial_port *port, struct file *file) } -static int digi_tiocmset(struct usb_serial_port *port, struct file *file, +static int digi_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); unsigned int val; unsigned long flags; @@ -1132,30 +1144,11 @@ static int digi_tiocmset(struct usb_serial_port *port, struct file *file, } -static int digi_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct digi_port *priv = usb_get_serial_port_data(port); - dbg("digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd); - - switch (cmd) { - case TIOCMIWAIT: - /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ - /* TODO */ - return 0; - case TIOCGICOUNT: - /* return count of modemline transitions */ - /* TODO */ - return 0; - } - return -ENOIOCTLCMD; - -} - -static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count) +static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { - int ret,data_len,new_len; + int ret, data_len, new_len; struct digi_port *priv = usb_get_serial_port_data(port); unsigned char *data = port->write_urb->transfer_buffer; unsigned long flags = 0; @@ -1173,7 +1166,8 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in spin_lock_irqsave(&priv->dp_port_lock, flags); /* wait for urb status clear to submit another urb */ - if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) { + if (port->write_urb->status == -EINPROGRESS || + priv->dp_write_urb_in_use) { /* buffer data if count is 1 (probably put_char) if possible */ if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) { priv->dp_out_buf[priv->dp_out_buf_len++] = *buf; @@ -1208,7 +1202,8 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in /* copy in new data */ memcpy(data, buf, new_len); - if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) { + ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); + if (ret == 0) { priv->dp_write_urb_in_use = 1; ret = new_len; priv->dp_out_buf_len = 0; @@ -1222,7 +1217,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in dbg("digi_write: returning %d", ret); return ret; -} +} static void digi_write_bulk_callback(struct urb *urb) { @@ -1237,13 +1232,13 @@ static void digi_write_bulk_callback(struct urb *urb) dbg("digi_write_bulk_callback: TOP, urb->status=%d", status); /* port and serial sanity check */ - if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) { + if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { err("%s: port or port->private is NULL, status=%d", __func__, status); return; } serial = port->serial; - if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) { + if (serial == NULL || (serial_priv = usb_get_serial_data(serial)) == NULL) { err("%s: serial or serial->private is NULL, status=%d", __func__, status); return; @@ -1262,17 +1257,19 @@ static void digi_write_bulk_callback(struct urb *urb) /* try to send any buffered data on this port, if it is open */ spin_lock(&priv->dp_port_lock); priv->dp_write_urb_in_use = 0; - if (port->open_count && port->write_urb->status != -EINPROGRESS + if (port->port.count && port->write_urb->status != -EINPROGRESS && priv->dp_out_buf_len > 0) { *((unsigned char *)(port->write_urb->transfer_buffer)) = (unsigned char)DIGI_CMD_SEND_DATA; - *((unsigned char *)(port->write_urb->transfer_buffer)+1) + *((unsigned char *)(port->write_urb->transfer_buffer) + 1) = (unsigned char)priv->dp_out_buf_len; - port->write_urb->transfer_buffer_length = priv->dp_out_buf_len+2; + port->write_urb->transfer_buffer_length = + priv->dp_out_buf_len + 2; port->write_urb->dev = serial->dev; - memcpy(port->write_urb->transfer_buffer+2, priv->dp_out_buf, + memcpy(port->write_urb->transfer_buffer + 2, priv->dp_out_buf, priv->dp_out_buf_len); - if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) { + ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); + if (ret == 0) { priv->dp_write_urb_in_use = 1; priv->dp_out_buf_len = 0; } @@ -1289,16 +1286,17 @@ static void digi_write_bulk_callback(struct urb *urb) __func__, ret, priv->dp_port_num); } -static int digi_write_room(struct usb_serial_port *port) +static int digi_write_room(struct tty_struct *tty) { - - int room; + struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); + int room; unsigned long flags = 0; spin_lock_irqsave(&priv->dp_port_lock, flags); - if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) + if (port->write_urb->status == -EINPROGRESS || + priv->dp_write_urb_in_use) room = 0; else room = port->bulk_out_size - 2 - priv->dp_out_buf_len; @@ -1309,12 +1307,11 @@ static int digi_write_room(struct usb_serial_port *port) } -static int digi_chars_in_buffer(struct usb_serial_port *port) +static int digi_chars_in_buffer(struct tty_struct *tty) { - + struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); - if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) { dbg("digi_chars_in_buffer: port=%d, chars=%d", @@ -1330,7 +1327,8 @@ static int digi_chars_in_buffer(struct usb_serial_port *port) } -static int digi_open(struct usb_serial_port *port, struct file *filp) +static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { int ret; unsigned char buf[32]; @@ -1339,7 +1337,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp) unsigned long flags = 0; dbg("digi_open: TOP: port=%d, open_count=%d", - priv->dp_port_num, port->open_count); + priv->dp_port_num, port->port.count); /* be sure the device is started up */ if (digi_startup_device(port->serial) != 0) @@ -1354,7 +1352,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp) } /* wait for a close in progress to finish */ - while(priv->dp_in_close) { + while (priv->dp_in_close) { cond_wait_interruptible_timeout_irqrestore( &priv->dp_close_wait, DIGI_RETRY_TIMEOUT, &priv->dp_port_lock, flags); @@ -1364,7 +1362,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp) } spin_unlock_irqrestore(&priv->dp_port_lock, flags); - + /* read modem signals automatically whenever they change */ buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; buf[1] = priv->dp_port_num; @@ -1377,13 +1375,16 @@ static int digi_open(struct usb_serial_port *port, struct file *filp) buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; buf[7] = 0; - if ((ret = digi_write_oob_command(port, buf, 8, 1)) != 0) + ret = digi_write_oob_command(port, buf, 8, 1); + if (ret != 0) dbg("digi_open: write oob failed, ret=%d", ret); /* set termios settings */ - not_termios.c_cflag = ~port->tty->termios->c_cflag; - not_termios.c_iflag = ~port->tty->termios->c_iflag; - digi_set_termios(port, ¬_termios); + if (tty) { + not_termios.c_cflag = ~tty->termios->c_cflag; + not_termios.c_iflag = ~tty->termios->c_iflag; + digi_set_termios(tty, port, ¬_termios); + } /* set DTR and RTS */ digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1); @@ -1392,16 +1393,16 @@ static int digi_open(struct usb_serial_port *port, struct file *filp) } -static void digi_close(struct usb_serial_port *port, struct file *filp) +static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { DEFINE_WAIT(wait); int ret; unsigned char buf[32]; - struct tty_struct *tty = port->tty; struct digi_port *priv = usb_get_serial_port_data(port); dbg("digi_close: TOP: port=%d, open_count=%d", - priv->dp_port_num, port->open_count); + priv->dp_port_num, port->port.count); mutex_lock(&port->serial->disc_mutex); /* if disconnected, just clear flags */ @@ -1426,9 +1427,8 @@ static void digi_close(struct usb_serial_port *port, struct file *filp) if (port->serial->dev) { /* wait for transmit idle */ - if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) { + if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); - } /* drop DTR and RTS */ digi_set_modem_signals(port, 0, 0); @@ -1462,11 +1462,13 @@ static void digi_close(struct usb_serial_port *port, struct file *filp) buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; buf[19] = 0; - if ((ret = digi_write_oob_command(port, buf, 20, 0)) != 0) + ret = digi_write_oob_command(port, buf, 20, 0); + if (ret != 0) dbg("digi_close: write oob failed, ret=%d", ret); /* wait for final commands on oob port to complete */ - prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE); + prepare_to_wait(&priv->dp_flush_wait, &wait, + TASK_INTERRUPTIBLE); schedule_timeout(DIGI_CLOSE_TIMEOUT); finish_wait(&priv->dp_flush_wait, &wait); @@ -1486,15 +1488,15 @@ exit: /* -* Digi Startup Device -* -* Starts reads on all ports. Must be called AFTER startup, with -* urbs initialized. Returns 0 if successful, non-zero error otherwise. -*/ + * Digi Startup Device + * + * Starts reads on all ports. Must be called AFTER startup, with + * urbs initialized. Returns 0 if successful, non-zero error otherwise. + */ static int digi_startup_device(struct usb_serial *serial) { - int i,ret = 0; + int i, ret = 0; struct digi_serial *serial_priv = usb_get_serial_data(serial); struct usb_serial_port *port; @@ -1512,7 +1514,8 @@ static int digi_startup_device(struct usb_serial *serial) for (i = 0; i < serial->type->num_ports + 1; i++) { port = serial->port[i]; port->write_urb->dev = port->serial->dev; - if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) { + ret = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (ret != 0) { err("%s: usb_submit_urb failed, ret=%d, port=%d", __func__, ret, i); break; @@ -1533,7 +1536,7 @@ static int digi_startup(struct usb_serial *serial) /* allocate the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ - for(i = 0; i < serial->type->num_ports + 1; i++) { + for (i = 0; i < serial->type->num_ports + 1; i++) { /* allocate port private structure */ priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); if (priv == NULL) { @@ -1596,7 +1599,7 @@ static void digi_shutdown(struct usb_serial *serial) /* free the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ - for(i = 0; i < serial->type->num_ports + 1; i++) + for (i = 0; i < serial->type->num_ports + 1; i++) kfree(usb_get_serial_port_data(serial->port[i])); kfree(usb_get_serial_data(serial)); } @@ -1619,7 +1622,7 @@ static void digi_read_bulk_callback(struct urb *urb) return; } if (port->serial == NULL || - (serial_priv=usb_get_serial_data(port->serial)) == NULL) { + (serial_priv = usb_get_serial_data(port->serial)) == NULL) { err("%s: serial is bad or serial->private is NULL, status=%d", __func__, status); return; @@ -1643,45 +1646,46 @@ static void digi_read_bulk_callback(struct urb *urb) /* continue read */ urb->dev = port->serial->dev; - if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret != 0) { err("%s: failed resubmitting urb, ret=%d, port=%d", __func__, ret, priv->dp_port_num); } } -/* -* Digi Read INB Callback -* -* Digi Read INB Callback handles reads on the in band ports, sending -* the data on to the tty subsystem. When called we know port and -* port->private are not NULL and port->serial has been validated. -* It returns 0 if successful, 1 if successful but the port is -* throttled, and -1 if the sanity checks failed. -*/ +/* + * Digi Read INB Callback + * + * Digi Read INB Callback handles reads on the in band ports, sending + * the data on to the tty subsystem. When called we know port and + * port->private are not NULL and port->serial has been validated. + * It returns 0 if successful, 1 if successful but the port is + * throttled, and -1 if the sanity checks failed. + */ static int digi_read_inb_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct tty_struct *tty = port->tty; + struct tty_struct *tty = port->port.tty; struct digi_port *priv = usb_get_serial_port_data(port); int opcode = ((unsigned char *)urb->transfer_buffer)[0]; int len = ((unsigned char *)urb->transfer_buffer)[1]; int port_status = ((unsigned char *)urb->transfer_buffer)[2]; - unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3; - int flag,throttled; + unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3; + int flag, throttled; int i; int status = urb->status; /* do not process callbacks on closed ports */ /* but do continue the read chain */ - if (port->open_count == 0) + if (port->port.count == 0) return 0; /* short/multiple packet check */ if (urb->actual_length != len + 2) { - err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, " + err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, " "port=%d, opcode=%d, len=%d, actual_length=%d, " "status=%d", __func__, status, priv->dp_port_num, opcode, len, urb->actual_length, port_status); @@ -1723,8 +1727,9 @@ static int digi_read_inb_callback(struct urb *urb) if (flag == TTY_NORMAL) tty_insert_flip_string(tty, data, len); else { - for(i = 0; i < len; i++) - tty_insert_flip_char(tty, data[i], flag); + for (i = 0; i < len; i++) + tty_insert_flip_char(tty, + data[i], flag); } tty_flip_buffer_push(tty); } @@ -1736,19 +1741,19 @@ static int digi_read_inb_callback(struct urb *urb) else if (opcode != DIGI_CMD_RECEIVE_DATA) dbg("%s: unknown opcode: %d", __func__, opcode); - return(throttled ? 1 : 0); + return throttled ? 1 : 0; } -/* -* Digi Read OOB Callback -* -* Digi Read OOB Callback handles reads on the out of band port. -* When called we know port and port->private are not NULL and -* the port->serial is valid. It returns 0 if successful, and -* -1 if the sanity checks failed. -*/ +/* + * Digi Read OOB Callback + * + * Digi Read OOB Callback handles reads on the out of band port. + * When called we know port and port->private are not NULL and + * the port->serial is valid. It returns 0 if successful, and + * -1 if the sanity checks failed. + */ static int digi_read_oob_callback(struct urb *urb) { @@ -1758,12 +1763,13 @@ static int digi_read_oob_callback(struct urb *urb) struct digi_port *priv = usb_get_serial_port_data(port); int opcode, line, status, val; int i; + unsigned int rts; dbg("digi_read_oob_callback: port=%d, len=%d", priv->dp_port_num, urb->actual_length); /* handle each oob command */ - for(i = 0; i < urb->actual_length - 3;) { + for (i = 0; i < urb->actual_length - 3;) { opcode = ((unsigned char *)urb->transfer_buffer)[i++]; line = ((unsigned char *)urb->transfer_buffer)[i++]; status = ((unsigned char *)urb->transfer_buffer)[i++]; @@ -1777,27 +1783,29 @@ static int digi_read_oob_callback(struct urb *urb) port = serial->port[line]; - if ((priv=usb_get_serial_port_data(port)) == NULL) + priv = usb_get_serial_port_data(port); + if (priv == NULL) return -1; + rts = 0; + if (port->port.count) + rts = port->port.tty->termios->c_cflag & CRTSCTS; + if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { spin_lock(&priv->dp_port_lock); /* convert from digi flags to termiox flags */ if (val & DIGI_READ_INPUT_SIGNALS_CTS) { priv->dp_modem_signals |= TIOCM_CTS; /* port must be open to use tty struct */ - if (port->open_count - && port->tty->termios->c_cflag & CRTSCTS) { - port->tty->hw_stopped = 0; + if (rts) { + port->port.tty->hw_stopped = 0; digi_wakeup_write(port); } } else { priv->dp_modem_signals &= ~TIOCM_CTS; /* port must be open to use tty struct */ - if (port->open_count - && port->tty->termios->c_cflag & CRTSCTS) { - port->tty->hw_stopped = 1; - } + if (rts) + port->port.tty->hw_stopped = 1; } if (val & DIGI_READ_INPUT_SIGNALS_DSR) priv->dp_modem_signals |= TIOCM_DSR; @@ -1834,7 +1842,7 @@ static int __init digi_init(void) if (retval) goto failed_acceleport_2_device; retval = usb_serial_register(&digi_acceleport_4_device); - if (retval) + if (retval) goto failed_acceleport_4_device; retval = usb_register(&digi_driver); if (retval) diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index c5ec309a3cb1..a6ab5b58d9ca 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -11,36 +11,39 @@ * it under the terms of the GNU General Public License, as published by * the Free Software Foundation, version 2. * - * See Documentation/usb/usb-serial.txt for more information on using this driver - * + * See Documentation/usb/usb-serial.txt for more information on using this + * driver + * * (07/16/2001) gb - * remove unused code in empeg_close() (thanks to Oliver Neukum for pointing this - * out) and rewrote empeg_set_termios(). - * + * remove unused code in empeg_close() (thanks to Oliver Neukum for + * pointing this out) and rewrote empeg_set_termios(). + * * (05/30/2001) gkh - * switched from using spinlock to a semaphore, which fixes lots of problems. + * switched from using spinlock to a semaphore, which fixes lots of + * problems. * * (04/08/2001) gb * Identify version on module load. - * + * * (01/22/2001) gb - * Added write_room() and chars_in_buffer() support. - * + * Added write_room() and chars_in_buffer() support. + * * (12/21/2000) gb * Moved termio stuff inside the port->active check. * Moved MOD_DEC_USE_COUNT to end of empeg_close(). - * + * * (12/03/2000) gb - * Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open() - * This notifies the tty driver that the termios have changed. - * + * Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to + * empeg_open(). This notifies the tty driver that the termios have + * changed. + * * (11/13/2000) gb - * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open() - * (It only needs to be set once - Doh!) - * + * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to + * empeg_open() (It only needs to be set once - Doh!) + * * (11/11/2000) gb * Updated to work with id_table structure. - * + * * (11/04/2000) gb * Forked this from visor.c, and hacked it up to work with an * Empeg ltd. empeg-car player. Constructive criticism welcomed. @@ -48,7 +51,7 @@ * use of his code, and for his guidance, advice and patience. :) * A 'Thank You' is in order for John Ripley of Empeg ltd for his * advice, and patience too. - * + * */ #include <linux/kernel.h> @@ -60,7 +63,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -77,31 +80,30 @@ static int debug; #define EMPEG_PRODUCT_ID 0x0001 /* function prototypes for an empeg-car player */ -static int empeg_open (struct usb_serial_port *port, struct file *filp); -static void empeg_close (struct usb_serial_port *port, struct file *filp); -static int empeg_write (struct usb_serial_port *port, - const unsigned char *buf, - int count); -static int empeg_write_room (struct usb_serial_port *port); -static int empeg_chars_in_buffer (struct usb_serial_port *port); -static void empeg_throttle (struct usb_serial_port *port); -static void empeg_unthrottle (struct usb_serial_port *port); -static int empeg_startup (struct usb_serial *serial); -static void empeg_shutdown (struct usb_serial *serial); -static int empeg_ioctl (struct usb_serial_port *port, - struct file * file, - unsigned int cmd, - unsigned long arg); -static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); -static void empeg_write_bulk_callback (struct urb *urb); -static void empeg_read_bulk_callback (struct urb *urb); +static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, + int count); +static int empeg_write_room(struct tty_struct *tty); +static int empeg_chars_in_buffer(struct tty_struct *tty); +static void empeg_throttle(struct tty_struct *tty); +static void empeg_unthrottle(struct tty_struct *tty); +static int empeg_startup(struct usb_serial *serial); +static void empeg_shutdown(struct usb_serial *serial); +static void empeg_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios); +static void empeg_write_bulk_callback(struct urb *urb); +static void empeg_read_bulk_callback(struct urb *urb); static struct usb_device_id id_table [] = { { USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver empeg_driver = { .name = "empeg", @@ -125,7 +127,6 @@ static struct usb_serial_driver empeg_device = { .unthrottle = empeg_unthrottle, .attach = empeg_startup, .shutdown = empeg_shutdown, - .ioctl = empeg_ioctl, .set_termios = empeg_set_termios, .write = empeg_write, .write_room = empeg_write_room, @@ -145,7 +146,8 @@ static int bytes_out; /****************************************************************************** * Empeg specific driver functions ******************************************************************************/ -static int empeg_open (struct usb_serial_port *port, struct file *filp) +static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { struct usb_serial *serial = port->serial; int result = 0; @@ -153,7 +155,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp) dbg("%s - port %d", __func__, port->number); /* Force default termio settings */ - empeg_set_termios (port, NULL) ; + empeg_set_termios(tty, port, NULL) ; bytes_in = 0; bytes_out = 0; @@ -161,7 +163,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp) /* Start reading from the device */ usb_fill_bulk_urb( port->read_urb, - serial->dev, + serial->dev, usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, @@ -172,13 +174,16 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp) result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) - dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); return result; } -static void empeg_close (struct usb_serial_port *port, struct file * filp) +static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { dbg("%s - port %d", __func__, port->number); @@ -189,7 +194,8 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp) } -static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, int count) +static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct urb *urb; @@ -203,11 +209,10 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, dbg("%s - port %d", __func__, port->number); while (count > 0) { - /* try to find a free urb in our list of them */ urb = NULL; - spin_lock_irqsave (&write_urb_pool_lock, flags); + spin_lock_irqsave(&write_urb_pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { if (write_urb_pool[i]->status != -EINPROGRESS) { @@ -216,7 +221,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, } } - spin_unlock_irqrestore (&write_urb_pool_lock, flags); + spin_unlock_irqrestore(&write_urb_pool_lock, flags); if (urb == NULL) { dbg("%s - no more free urbs", __func__); @@ -224,25 +229,27 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, } if (urb->transfer_buffer == NULL) { - urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); + urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); if (urb->transfer_buffer == NULL) { - dev_err(&port->dev, "%s no more kernel memory...\n", __func__); + dev_err(&port->dev, + "%s no more kernel memory...\n", + __func__); goto exit; } } - transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE); + transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); - memcpy (urb->transfer_buffer, current_position, transfer_size); + memcpy(urb->transfer_buffer, current_position, transfer_size); usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer); /* build up our urb */ - usb_fill_bulk_urb ( + usb_fill_bulk_urb( urb, serial->dev, usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), + port->bulk_out_endpointAddress), urb->transfer_buffer, transfer_size, empeg_write_bulk_callback, @@ -262,66 +269,57 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, bytes_out += transfer_size; } - exit: return bytes_sent; - -} +} -static int empeg_write_room (struct usb_serial_port *port) +static int empeg_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; unsigned long flags; int i; int room = 0; dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave (&write_urb_pool_lock, flags); - + spin_lock_irqsave(&write_urb_pool_lock, flags); /* tally up the number of bytes available */ for (i = 0; i < NUM_URBS; ++i) { - if (write_urb_pool[i]->status != -EINPROGRESS) { + if (write_urb_pool[i]->status != -EINPROGRESS) room += URB_TRANSFER_BUFFER_SIZE; - } - } - - spin_unlock_irqrestore (&write_urb_pool_lock, flags); - + } + spin_unlock_irqrestore(&write_urb_pool_lock, flags); dbg("%s - returns %d", __func__, room); - - return (room); + return room; } -static int empeg_chars_in_buffer (struct usb_serial_port *port) +static int empeg_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; unsigned long flags; int i; int chars = 0; dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave (&write_urb_pool_lock, flags); + spin_lock_irqsave(&write_urb_pool_lock, flags); /* tally up the number of bytes waiting */ for (i = 0; i < NUM_URBS; ++i) { - if (write_urb_pool[i]->status == -EINPROGRESS) { + if (write_urb_pool[i]->status == -EINPROGRESS) chars += URB_TRANSFER_BUFFER_SIZE; - } } - spin_unlock_irqrestore (&write_urb_pool_lock, flags); - + spin_unlock_irqrestore(&write_urb_pool_lock, flags); dbg("%s - returns %d", __func__, chars); - - return (chars); - + return chars; } -static void empeg_write_bulk_callback (struct urb *urb) +static void empeg_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; int status = urb->status; @@ -338,7 +336,7 @@ static void empeg_write_bulk_callback (struct urb *urb) } -static void empeg_read_bulk_callback (struct urb *urb) +static void empeg_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct tty_struct *tty; @@ -354,9 +352,9 @@ static void empeg_read_bulk_callback (struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - - tty = port->tty; + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); + tty = port->port.tty; if (urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); @@ -368,7 +366,7 @@ static void empeg_read_bulk_callback (struct urb *urb) /* Continue trying to always read */ usb_fill_bulk_urb( port->read_urb, - port->serial->dev, + port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, @@ -379,38 +377,39 @@ static void empeg_read_bulk_callback (struct urb *urb) result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); + dev_err(&urb->dev->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); return; } -static void empeg_throttle (struct usb_serial_port *port) +static void empeg_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); usb_kill_urb(port->read_urb); } -static void empeg_unthrottle (struct usb_serial_port *port) +static void empeg_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int result; - dbg("%s - port %d", __func__, port->number); port->read_urb->dev = port->serial->dev; - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); - - return; + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); } -static int empeg_startup (struct usb_serial *serial) +static int empeg_startup(struct usb_serial *serial) { int r; @@ -422,7 +421,7 @@ static int empeg_startup (struct usb_serial *serial) return -ENODEV; } dbg("%s - reset config", __func__); - r = usb_reset_configuration (serial->dev); + r = usb_reset_configuration(serial->dev); /* continue on with initialization */ return r; @@ -430,34 +429,27 @@ static int empeg_startup (struct usb_serial *serial) } -static void empeg_shutdown (struct usb_serial *serial) +static void empeg_shutdown(struct usb_serial *serial) { - dbg ("%s", __func__); -} - - -static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) -{ - dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); - - return -ENOIOCTLCMD; + dbg("%s", __func__); } -static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) +static void empeg_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { - struct ktermios *termios = port->tty->termios; + struct ktermios *termios = tty->termios; dbg("%s - port %d", __func__, port->number); /* - * The empeg-car player wants these particular tty settings. - * You could, for example, change the baud rate, however the - * player only supports 115200 (currently), so there is really - * no point in support for changes to the tty settings. - * (at least for now) - * - * The default requirements for this device are: - */ + * The empeg-car player wants these particular tty settings. + * You could, for example, change the baud rate, however the + * player only supports 115200 (currently), so there is really + * no point in support for changes to the tty settings. + * (at least for now) + * + * The default requirements for this device are: + */ termios->c_iflag &= ~(IGNBRK /* disable ignore break */ | BRKINT /* disable break causes interrupt */ @@ -491,18 +483,18 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol * this is bad as it opens up the possibility of dropping bytes * on the floor. We don't want to drop bytes on the floor. :) */ - port->tty->low_latency = 1; - tty_encode_baud_rate(port->tty, 115200, 115200); + tty->low_latency = 1; + tty_encode_baud_rate(tty, 115200, 115200); } -static int __init empeg_init (void) +static int __init empeg_init(void) { struct urb *urb; int i, retval; - /* create our write urb pool and transfer buffers */ - spin_lock_init (&write_urb_pool_lock); + /* create our write urb pool and transfer buffers */ + spin_lock_init(&write_urb_pool_lock); for (i = 0; i < NUM_URBS; ++i) { urb = usb_alloc_urb(0, GFP_KERNEL); write_urb_pool[i] = urb; @@ -511,9 +503,10 @@ static int __init empeg_init (void) continue; } - urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, + GFP_KERNEL); if (!urb->transfer_buffer) { - err("%s - out of memory for urb buffers.", + err("%s - out of memory for urb buffers.", __func__); continue; } @@ -542,36 +535,36 @@ failed_usb_serial_register: } -static void __exit empeg_exit (void) +static void __exit empeg_exit(void) { int i; unsigned long flags; usb_deregister(&empeg_driver); - usb_serial_deregister (&empeg_device); + usb_serial_deregister(&empeg_device); - spin_lock_irqsave (&write_urb_pool_lock, flags); + spin_lock_irqsave(&write_urb_pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { if (write_urb_pool[i]) { - /* FIXME - uncomment the following usb_kill_urb call when - * the host controllers get fixed to set urb->dev = NULL after - * the urb is finished. Otherwise this call oopses. */ + /* FIXME - uncomment the following usb_kill_urb call + * when the host controllers get fixed to set urb->dev + * = NULL after the urb is finished. Otherwise this + * call oopses. */ /* usb_kill_urb(write_urb_pool[i]); */ kfree(write_urb_pool[i]->transfer_buffer); - usb_free_urb (write_urb_pool[i]); + usb_free_urb(write_urb_pool[i]); } } - - spin_unlock_irqrestore (&write_urb_pool_lock, flags); + spin_unlock_irqrestore(&write_urb_pool_lock, flags); } module_init(empeg_init); module_exit(empeg_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index cc4fbd9d60be..711e84f6ed82 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -20,7 +20,8 @@ /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ #define CPUCS_REG 0x7F92 -int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest) +int ezusb_writememory(struct usb_serial *serial, int address, + unsigned char *data, int length, __u8 request) { int result; unsigned char *transfer_buffer; @@ -33,26 +34,27 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da transfer_buffer = kmemdup(data, length, GFP_KERNEL); if (!transfer_buffer) { - dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length); + dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", + __func__, length); return -ENOMEM; } - result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000); - kfree (transfer_buffer); + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + request, 0x40, address, 0, transfer_buffer, length, 3000); + kfree(transfer_buffer); return result; } +EXPORT_SYMBOL_GPL(ezusb_writememory); -int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit) +int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit) { int response; /* dbg("%s - %d", __func__, reset_bit); */ - response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0); + response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0); if (response < 0) - dev_err(&serial->dev->dev, "%s- %d failed\n", __func__, reset_bit); + dev_err(&serial->dev->dev, "%s- %d failed\n", + __func__, reset_bit); return response; } - - -EXPORT_SYMBOL_GPL(ezusb_writememory); EXPORT_SYMBOL_GPL(ezusb_set_reset); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0ff4a3971e45..838717250145 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -12,7 +12,8 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * See http://ftdi-usb-sio.sourceforge.net for upto date testing info * and extra documentation @@ -25,7 +26,8 @@ /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ /* Thanx to FTDI for so kindly providing details of the protocol required */ /* to talk to the device */ -/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */ +/* Thanx to gkh and the rest of the usb dev group for all code I have + assimilated :-) */ #include <linux/kernel.h> #include <linux/errno.h> @@ -36,7 +38,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/serial.h> #include <linux/usb/serial.h> @@ -55,17 +57,22 @@ static __u16 product; struct ftdi_private { ftdi_chip_type_t chip_type; - /* type of the device, either SIO or FT8U232AM */ + /* type of device, either SIO or FT8U232AM */ int baud_base; /* baud base clock for divisor setting */ - int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ + int custom_divisor; /* custom_divisor kludge, this is for + baud_base (different from what goes to the + chip!) */ __u16 last_set_data_urb_value ; - /* the last data state set - needed for doing a break */ - int write_offset; /* This is the offset in the usb data block to write the serial data - - * it is different between devices + /* the last data state set - needed for doing + * a break + */ + int write_offset; /* This is the offset in the usb data block to + * write the serial data - it varies between + * devices */ int flags; /* some ASYNC_xxxx flags are supported */ unsigned long last_dtr_rts; /* saved modem control outputs */ - wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ + wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ char prev_status, diff_status; /* Used for TIOCMIWAIT */ __u8 rx_flags; /* receive state flags (throttling) */ spinlock_t rx_lock; /* spinlock for receive state */ @@ -76,8 +83,10 @@ struct ftdi_private { __u16 interface; /* FT2232C port interface (0 for FT232/245) */ - speed_t force_baud; /* if non-zero, force the baud rate to this value */ - int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ + speed_t force_baud; /* if non-zero, force the baud rate to + this value */ + int force_rtscts; /* if non-zero, force RTS-CTS to always + be enabled */ spinlock_t tx_lock; /* spinlock for transmit state */ unsigned long tx_bytes; @@ -88,13 +97,14 @@ struct ftdi_private { /* struct ftdi_sio_quirk is used by devices requiring special attention. */ struct ftdi_sio_quirk { int (*probe)(struct usb_serial *); - void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */ + /* Special settings for probed ports. */ + void (*port_probe)(struct ftdi_private *); }; -static int ftdi_jtag_probe (struct usb_serial *serial); -static int ftdi_mtxorb_hack_setup (struct usb_serial *serial); -static void ftdi_USB_UIRT_setup (struct ftdi_private *priv); -static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv); +static int ftdi_jtag_probe(struct usb_serial *serial); +static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); +static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); +static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); static struct ftdi_sio_quirk ftdi_jtag_quirk = { .probe = ftdi_jtag_probe, @@ -174,270 +184,270 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0100_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0101_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0102_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0103_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0104_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0105_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0106_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0107_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0108_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0109_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0110_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0111_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0112_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0113_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0114_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0115_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0116_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0117_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0118_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0119_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0120_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0121_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0122_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0123_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0124_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0125_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0126_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0127_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0128_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0129_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012C_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0130_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0131_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0132_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0133_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0134_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0135_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0136_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0137_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0138_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0139_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0140_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0141_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0142_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0143_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0144_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0145_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0146_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0147_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0148_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0149_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0150_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0151_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0152_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0153_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0154_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0155_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0156_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0157_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0158_PID), + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0159_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0160_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0161_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0162_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0163_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0164_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0165_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0166_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0167_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0168_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0169_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0170_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0171_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0172_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0173_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0174_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0175_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0176_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0177_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0178_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0179_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0180_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0181_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0182_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0183_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0184_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0185_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0186_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0187_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0188_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0189_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0190_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0191_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0192_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0193_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0194_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0195_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0196_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0197_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0198_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0199_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019A_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019B_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019C_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019D_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019E_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019F_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A0_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A1_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A2_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A3_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A4_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A5_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A6_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A7_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A8_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A9_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AA_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AB_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AC_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AD_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AE_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AF_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B0_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B1_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B2_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B3_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B4_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B5_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B6_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B7_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B8_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B9_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BA_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BB_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BC_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BD_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BE_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BF_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C0_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C1_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C2_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C3_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C4_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C5_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C6_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C7_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C8_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C9_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CA_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CB_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CC_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CD_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CE_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CF_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D0_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D1_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D2_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D3_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D4_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D5_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D6_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D7_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D8_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D9_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DA_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DB_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DC_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DD_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DE_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DF_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E0_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E1_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E2_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E3_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E4_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E5_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E6_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E7_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E8_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E9_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EA_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EB_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EC_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01ED_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EE_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EF_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F0_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F1_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F2_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F3_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F4_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F5_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F6_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F7_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F8_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F9_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FA_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FB_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FC_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FD_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FE_PID) }, - { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, @@ -642,7 +652,7 @@ static struct usb_device_id id_table_combined [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver ftdi_driver = { .name = "ftdi_sio", @@ -678,30 +688,37 @@ static const char *ftdi_chip_name[] = { | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP) /* function prototypes for a FTDI serial converter */ -static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); -static void ftdi_shutdown (struct usb_serial *serial); -static int ftdi_sio_port_probe (struct usb_serial_port *port); -static int ftdi_sio_port_remove (struct usb_serial_port *port); -static int ftdi_open (struct usb_serial_port *port, struct file *filp); -static void ftdi_close (struct usb_serial_port *port, struct file *filp); -static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static int ftdi_write_room (struct usb_serial_port *port); -static int ftdi_chars_in_buffer (struct usb_serial_port *port); -static void ftdi_write_bulk_callback (struct urb *urb); -static void ftdi_read_bulk_callback (struct urb *urb); -static void ftdi_process_read (struct work_struct *work); -static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old); -static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); -static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); -static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void ftdi_break_ctl (struct usb_serial_port *port, int break_state ); -static void ftdi_throttle (struct usb_serial_port *port); -static void ftdi_unthrottle (struct usb_serial_port *port); - -static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base); -static unsigned short int ftdi_232am_baud_to_divisor (int baud); -static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base); -static __u32 ftdi_232bm_baud_to_divisor (int baud); +static int ftdi_sio_probe(struct usb_serial *serial, + const struct usb_device_id *id); +static void ftdi_shutdown(struct usb_serial *serial); +static int ftdi_sio_port_probe(struct usb_serial_port *port); +static int ftdi_sio_port_remove(struct usb_serial_port *port); +static int ftdi_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void ftdi_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static int ftdi_write_room(struct tty_struct *tty); +static int ftdi_chars_in_buffer(struct tty_struct *tty); +static void ftdi_write_bulk_callback(struct urb *urb); +static void ftdi_read_bulk_callback(struct urb *urb); +static void ftdi_process_read(struct work_struct *work); +static void ftdi_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); +static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static int ftdi_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void ftdi_break_ctl(struct tty_struct *tty, int break_state); +static void ftdi_throttle(struct tty_struct *tty); +static void ftdi_unthrottle(struct tty_struct *tty); + +static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); +static unsigned short int ftdi_232am_baud_to_divisor(int baud); +static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); +static __u32 ftdi_232bm_baud_to_divisor(int baud); static struct usb_serial_driver ftdi_sio_device = { .driver = { @@ -752,44 +769,54 @@ static struct usb_serial_driver ftdi_sio_device = { static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) { unsigned short int divisor; - int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left - if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1 + /* divisor shifted 3 bits to the left */ + int divisor3 = base / 2 / baud; + if ((divisor3 & 0x7) == 7) + divisor3++; /* round x.7/8 up to x+1 */ divisor = divisor3 >> 3; divisor3 &= 0x7; - if (divisor3 == 1) divisor |= 0xc000; else // 0.125 - if (divisor3 >= 4) divisor |= 0x4000; else // 0.5 - if (divisor3 != 0) divisor |= 0x8000; // 0.25 - if (divisor == 1) divisor = 0; /* special case for maximum baud rate */ + if (divisor3 == 1) + divisor |= 0xc000; + else if (divisor3 >= 4) + divisor |= 0x4000; + else if (divisor3 != 0) + divisor |= 0x8000; + else if (divisor == 1) + divisor = 0; /* special case for maximum baud rate */ return divisor; } static unsigned short int ftdi_232am_baud_to_divisor(int baud) { - return(ftdi_232am_baud_base_to_divisor(baud, 48000000)); + return ftdi_232am_baud_base_to_divisor(baud, 48000000); } static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) { static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; __u32 divisor; - int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left + /* divisor shifted 3 bits to the left */ + int divisor3 = base / 2 / baud; divisor = divisor3 >> 3; divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; /* Deal with special cases for highest baud rates. */ - if (divisor == 1) divisor = 0; else // 1.0 - if (divisor == 0x4001) divisor = 1; // 1.5 + if (divisor == 1) + divisor = 0; + else if (divisor == 0x4001) + divisor = 1; return divisor; } static __u32 ftdi_232bm_baud_to_divisor(int baud) { - return(ftdi_232bm_baud_base_to_divisor(baud, 48000000)); + return ftdi_232bm_baud_base_to_divisor(baud, 48000000); } #define set_mctrl(port, set) update_mctrl((port), (set), 0) #define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) -static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear) +static int update_mctrl(struct usb_serial_port *port, unsigned int set, + unsigned int clear) { struct ftdi_private *priv = usb_get_serial_port_data(port); char *buf; @@ -843,42 +870,8 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned } -static __u32 get_ftdi_divisor(struct usb_serial_port * port); - - -static int change_speed(struct usb_serial_port *port) -{ - struct ftdi_private *priv = usb_get_serial_port_data(port); - char *buf; - __u16 urb_value; - __u16 urb_index; - __u32 urb_index_value; - int rv; - - buf = kmalloc(1, GFP_NOIO); - if (!buf) - return -ENOMEM; - - urb_index_value = get_ftdi_divisor(port); - urb_value = (__u16)urb_index_value; - urb_index = (__u16)(urb_index_value >> 16); - if (priv->interface) { /* FT2232C */ - urb_index = (__u16)((urb_index << 8) | priv->interface); - } - - rv = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - FTDI_SIO_SET_BAUDRATE_REQUEST, - FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, - urb_value, urb_index, - buf, 0, WDR_SHORT_TIMEOUT); - - kfree(buf); - return rv; -} - - -static __u32 get_ftdi_divisor(struct usb_serial_port * port) +static __u32 get_ftdi_divisor(struct tty_struct *tty, + struct usb_serial_port *port) { /* get_ftdi_divisor */ struct ftdi_private *priv = usb_get_serial_port_data(port); __u32 div_value = 0; @@ -886,48 +879,56 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) int baud; /* - * The logic involved in setting the baudrate can be cleanly split in 3 steps. - * Obtaining the actual baud rate is a little tricky since unix traditionally - * somehow ignored the possibility to set non-standard baud rates. + * The logic involved in setting the baudrate can be cleanly split into + * 3 steps. * 1. Standard baud rates are set in tty->termios->c_cflag - * 2. If these are not enough, you can set any speed using alt_speed as follows: + * 2. If these are not enough, you can set any speed using alt_speed as + * follows: * - set tty->termios->c_cflag speed to B38400 * - set your real speed in tty->alt_speed; it gets ignored when * alt_speed==0, (or) - * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows: - * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just - * sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800) + * - call TIOCSSERIAL ioctl with (struct serial_struct) set as + * follows: + * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], + * this just sets alt_speed to (HI: 57600, VHI: 115200, + * SHI: 230400, WARP: 460800) * ** Steps 1, 2 are done courtesy of tty_get_baud_rate * 3. You can also set baud rate by setting custom divisor as follows * - set tty->termios->c_cflag speed to B38400 - * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows: + * - call TIOCSSERIAL ioctl with (struct serial_struct) set as + * follows: * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST * o custom_divisor set to baud_base / your_new_baudrate - * ** Step 3 is done courtesy of code borrowed from serial.c - I should really - * spend some time and separate+move this common code to serial.c, it is - * replicated in nearly every serial driver you see. + * ** Step 3 is done courtesy of code borrowed from serial.c + * I should really spend some time and separate + move this common + * code to serial.c, it is replicated in nearly every serial driver + * you see. */ - /* 1. Get the baud rate from the tty settings, this observes alt_speed hack */ + /* 1. Get the baud rate from the tty settings, this observes + alt_speed hack */ - baud = tty_get_baud_rate(port->tty); + baud = tty_get_baud_rate(tty); dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud); - /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */ + /* 2. Observe async-compatible custom_divisor hack, update baudrate + if needed */ if (baud == 38400 && ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (priv->custom_divisor)) { baud = priv->baud_base / priv->custom_divisor; - dbg("%s - custom divisor %d sets baud rate to %d", __func__, priv->custom_divisor, baud); + dbg("%s - custom divisor %d sets baud rate to %d", + __func__, priv->custom_divisor, baud); } /* 3. Convert baudrate to device-specific divisor */ - if (!baud) baud = 9600; - switch(priv->chip_type) { + if (!baud) + baud = 9600; + switch (priv->chip_type) { case SIO: /* SIO chip */ - switch(baud) { + switch (baud) { case 300: div_value = ftdi_sio_b300; break; case 600: div_value = ftdi_sio_b600; break; case 1200: div_value = ftdi_sio_b1200; break; @@ -940,7 +941,8 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) case 115200: div_value = ftdi_sio_b115200; break; } /* baud */ if (div_value == 0) { - dbg("%s - Baudrate (%d) requested is not supported", __func__, baud); + dbg("%s - Baudrate (%d) requested is not supported", + __func__, baud); div_value = ftdi_sio_b9600; baud = 9600; div_okay = 0; @@ -950,7 +952,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) if (baud <= 3000000) { div_value = ftdi_232am_baud_to_divisor(baud); } else { - dbg("%s - Baud rate too high!", __func__); + dbg("%s - Baud rate too high!", __func__); baud = 9600; div_value = ftdi_232am_baud_to_divisor(9600); div_okay = 0; @@ -962,7 +964,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) if (baud <= 3000000) { div_value = ftdi_232bm_baud_to_divisor(baud); } else { - dbg("%s - Baud rate too high!", __func__); + dbg("%s - Baud rate too high!", __func__); div_value = ftdi_232bm_baud_to_divisor(9600); div_okay = 0; baud = 9600; @@ -976,12 +978,45 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) ftdi_chip_name[priv->chip_type]); } - tty_encode_baud_rate(port->tty, baud, baud); - return(div_value); + tty_encode_baud_rate(tty, baud, baud); + return div_value; +} + +static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) +{ + struct ftdi_private *priv = usb_get_serial_port_data(port); + char *buf; + __u16 urb_value; + __u16 urb_index; + __u32 urb_index_value; + int rv; + + buf = kmalloc(1, GFP_NOIO); + if (!buf) + return -ENOMEM; + + urb_index_value = get_ftdi_divisor(tty, port); + urb_value = (__u16)urb_index_value; + urb_index = (__u16)(urb_index_value >> 16); + if (priv->interface) { /* FT2232C */ + urb_index = (__u16)((urb_index << 8) | priv->interface); + } + + rv = usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), + FTDI_SIO_SET_BAUDRATE_REQUEST, + FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, + urb_value, urb_index, + buf, 0, WDR_SHORT_TIMEOUT); + + kfree(buf); + return rv; } -static int get_serial_info(struct usb_serial_port * port, struct serial_struct __user * retinfo) + +static int get_serial_info(struct usb_serial_port *port, + struct serial_struct __user *retinfo) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct serial_struct tmp; @@ -998,7 +1033,8 @@ static int get_serial_info(struct usb_serial_port * port, struct serial_struct _ } /* get_serial_info */ -static int set_serial_info(struct usb_serial_port * port, struct serial_struct __user * newinfo) +static int set_serial_info(struct tty_struct *tty, + struct usb_serial_port *port, struct serial_struct __user *newinfo) { /* set_serial_info */ struct ftdi_private *priv = usb_get_serial_port_data(port); struct serial_struct new_serial; @@ -1006,7 +1042,7 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) return -EFAULT; - old_priv = * priv; + old_priv = *priv; /* Do error checking and permission checking */ @@ -1027,33 +1063,32 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _ /* Make the changes - these are privileged changes! */ priv->flags = ((priv->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); + (new_serial.flags & ASYNC_FLAGS)); priv->custom_divisor = new_serial.custom_divisor; - port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: if ((old_priv.flags & ASYNC_SPD_MASK) != (priv->flags & ASYNC_SPD_MASK)) { if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - port->tty->alt_speed = 57600; + tty->alt_speed = 57600; else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - port->tty->alt_speed = 115200; + tty->alt_speed = 115200; else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - port->tty->alt_speed = 230400; + tty->alt_speed = 230400; else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - port->tty->alt_speed = 460800; + tty->alt_speed = 460800; else - port->tty->alt_speed = 0; + tty->alt_speed = 0; } if (((old_priv.flags & ASYNC_SPD_MASK) != (priv->flags & ASYNC_SPD_MASK)) || (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (old_priv.custom_divisor != priv->custom_divisor))) { - change_speed(port); + change_speed(tty, port); } - - return (0); + return 0; } /* set_serial_info */ @@ -1082,11 +1117,10 @@ static void ftdi_determine_type(struct usb_serial_port *port) priv->chip_type = FT2232C; /* Determine interface code. */ inter = serial->interface->altsetting->desc.bInterfaceNumber; - if (inter == 0) { + if (inter == 0) priv->interface = PIT_SIOA; - } else { + else priv->interface = PIT_SIOB; - } /* BM-type devices have a bug where bcdDevice gets set * to 0x200 when iSerialNumber is 0. */ if (version < 0x500) { @@ -1120,7 +1154,8 @@ static void ftdi_determine_type(struct usb_serial_port *port) * *************************************************************************** */ -static ssize_t show_latency_timer(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_latency_timer(struct device *dev, + struct device_attribute *attr, char *buf) { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1129,14 +1164,14 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a int rv = 0; - dbg("%s",__func__); + dbg("%s", __func__); rv = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), FTDI_SIO_GET_LATENCY_TIMER_REQUEST, FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, 0, priv->interface, - (char*) &latency, 1, WDR_TIMEOUT); + (char *) &latency, 1, WDR_TIMEOUT); if (rv < 0) { dev_err(dev, "Unable to read latency timer: %i\n", rv); @@ -1146,8 +1181,9 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a } /* Write a new value of the latency timer, in units of milliseconds. */ -static ssize_t store_latency_timer(struct device *dev, struct device_attribute *attr, const char *valbuf, - size_t count) +static ssize_t store_latency_timer(struct device *dev, + struct device_attribute *attr, const char *valbuf, + size_t count) { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1175,8 +1211,8 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute * /* Write an event character directly to the FTDI register. The ASCII value is in the low 8 bits, with the enable bit in the 9th bit. */ -static ssize_t store_event_char(struct device *dev, struct device_attribute *attr, const char *valbuf, - size_t count) +static ssize_t store_event_char(struct device *dev, + struct device_attribute *attr, const char *valbuf, size_t count) { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1202,7 +1238,8 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att return count; } -static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); +static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, + store_latency_timer); static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); static int create_sysfs_attrs(struct usb_serial_port *port) @@ -1210,7 +1247,7 @@ static int create_sysfs_attrs(struct usb_serial_port *port) struct ftdi_private *priv = usb_get_serial_port_data(port); int retval = 0; - dbg("%s",__func__); + dbg("%s", __func__); /* XXX I've no idea if the original SIO supports the event_char * sysfs parameter, so I'm playing it safe. */ @@ -1232,7 +1269,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); - dbg("%s",__func__); + dbg("%s", __func__); /* XXX see create_sysfs_attrs */ if (priv->chip_type != SIO) { @@ -1253,9 +1290,11 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) */ /* Probe function to check for special devices */ -static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id) +static int ftdi_sio_probe(struct usb_serial *serial, + const struct usb_device_id *id) { - struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info; + struct ftdi_sio_quirk *quirk = + (struct ftdi_sio_quirk *)id->driver_info; if (quirk && quirk->probe) { int ret = quirk->probe(serial); @@ -1274,17 +1313,18 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); - dbg("%s",__func__); + dbg("%s", __func__); priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); - if (!priv){ - err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private)); + if (!priv) { + err("%s- kmalloc(%Zd) failed.", __func__, + sizeof(struct ftdi_private)); return -ENOMEM; } spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->tx_lock); - init_waitqueue_head(&priv->delta_msr_wait); + init_waitqueue_head(&priv->delta_msr_wait); /* This will push the characters through immediately rather than queue a task to deliver them */ priv->flags = ASYNC_LOW_LATENCY; @@ -1294,9 +1334,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) /* Increase the size of read buffers */ kfree(port->bulk_in_buffer); - port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); + port->bulk_in_buffer = kmalloc(BUFSZ, GFP_KERNEL); if (!port->bulk_in_buffer) { - kfree (priv); + kfree(priv); return -ENOMEM; } if (port->read_urb) { @@ -1309,7 +1349,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) /* Free port's existing write urb and transfer buffer. */ if (port->write_urb) { - usb_free_urb (port->write_urb); + usb_free_urb(port->write_urb); port->write_urb = NULL; } kfree(port->bulk_out_buffer); @@ -1317,7 +1357,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, priv); - ftdi_determine_type (port); + ftdi_determine_type(port); create_sysfs_attrs(port); return 0; } @@ -1325,9 +1365,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) /* Setup for the USB-UIRT device, which requires hardwired * baudrate (38400 gets mapped to 312500) */ /* Called from usbserial:serial_probe */ -static void ftdi_USB_UIRT_setup (struct ftdi_private *priv) +static void ftdi_USB_UIRT_setup(struct ftdi_private *priv) { - dbg("%s",__func__); + dbg("%s", __func__); priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 77; @@ -1336,9 +1376,10 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv) /* Setup for the HE-TIRA1 device, which requires hardwired * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ -static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv) + +static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) { - dbg("%s",__func__); + dbg("%s", __func__); priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 240; @@ -1356,7 +1397,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial) struct usb_device *udev = serial->dev; struct usb_interface *interface = serial->interface; - dbg("%s",__func__); + dbg("%s", __func__); if (interface == udev->actconfig->interface[0]) { info("Ignoring serial port reserved for JTAG"); @@ -1390,7 +1431,7 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial) * calls __serial_close for each open of the port * shutdown is called then (ie ftdi_shutdown) */ -static void ftdi_shutdown (struct usb_serial *serial) +static void ftdi_shutdown(struct usb_serial *serial) { dbg("%s", __func__); } @@ -1404,7 +1445,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) remove_sysfs_attrs(port); /* all open ports are closed at this point - * (by usbserial.c:__serial_close, which calls ftdi_close) + * (by usbserial.c:__serial_close, which calls ftdi_close) */ if (priv) { @@ -1415,7 +1456,8 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) return 0; } -static int ftdi_open (struct usb_serial_port *port, struct file *filp) +static int ftdi_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { /* ftdi_open */ struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1433,8 +1475,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) priv->rx_bytes = 0; spin_unlock_irqrestore(&priv->rx_lock, flags); - if (port->tty) - port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + if (tty) + tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ @@ -1448,8 +1490,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - if (port->tty) - ftdi_set_termios(port, port->tty->termios); + if (tty) + ftdi_set_termios(tty, port, tty->termios); /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ @@ -1464,12 +1506,14 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) /* Start reading from the device */ priv->rx_processed = 0; usb_fill_bulk_urb(port->read_urb, dev, - usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, - ftdi_read_bulk_callback, port); + usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ftdi_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) - err("%s - failed submitting read urb, error %d", __func__, result); + err("%s - failed submitting read urb, error %d", + __func__, result); return result; @@ -1485,16 +1529,17 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) * */ -static void ftdi_close (struct usb_serial_port *port, struct file *filp) +static void ftdi_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { /* ftdi_close */ - unsigned int c_cflag = port->tty->termios->c_cflag; + unsigned int c_cflag = tty->termios->c_cflag; struct ftdi_private *priv = usb_get_serial_port_data(port); char buf[1]; dbg("%s", __func__); mutex_lock(&port->serial->disc_mutex); - if (c_cflag & HUPCL && !port->serial->disconnected){ + if (c_cflag & HUPCL && !port->serial->disconnected) { /* Disable flow control */ if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), @@ -1527,7 +1572,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) * * The new devices do not require this byte */ -static int ftdi_write (struct usb_serial_port *port, +static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { /* ftdi_write */ struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1554,7 +1599,7 @@ static int ftdi_write (struct usb_serial_port *port, spin_unlock_irqrestore(&priv->tx_lock, flags); data_offset = priv->write_offset; - dbg("data_offset set to %d",data_offset); + dbg("data_offset set to %d", data_offset); /* Determine total transfer size */ transfer_size = count; @@ -1565,7 +1610,7 @@ static int ftdi_write (struct usb_serial_port *port, (PKTSZ - data_offset))); } - buffer = kmalloc (transfer_size, GFP_ATOMIC); + buffer = kmalloc(transfer_size, GFP_ATOMIC); if (!buffer) { err("%s ran out of kernel memory for urb ...", __func__); count = -ENOMEM; @@ -1581,20 +1626,20 @@ static int ftdi_write (struct usb_serial_port *port, /* Copy data */ if (data_offset > 0) { - /* Original sio requires control byte at start of each packet. */ + /* Original sio requires control byte at start of + each packet. */ int user_pktsz = PKTSZ - data_offset; int todo = count; unsigned char *first_byte = buffer; const unsigned char *current_position = buf; while (todo > 0) { - if (user_pktsz > todo) { + if (user_pktsz > todo) user_pktsz = todo; - } /* Write the control byte at the front of the packet*/ *first_byte = 1 | ((user_pktsz) << 2); /* Copy data for packet */ - memcpy (first_byte + data_offset, + memcpy(first_byte + data_offset, current_position, user_pktsz); first_byte += user_pktsz + data_offset; current_position += user_pktsz; @@ -1603,20 +1648,23 @@ static int ftdi_write (struct usb_serial_port *port, } else { /* No control byte required. */ /* Copy in the data to send */ - memcpy (buffer, buf, count); + memcpy(buffer, buf, count); } - usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer); + usb_serial_debug_data(debug, &port->dev, __func__, + transfer_size, buffer); /* fill the buffer and send it */ usb_fill_bulk_urb(urb, port->serial->dev, - usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), - buffer, transfer_size, - ftdi_write_bulk_callback, port); + usb_sndbulkpipe(port->serial->dev, + port->bulk_out_endpointAddress), + buffer, transfer_size, + ftdi_write_bulk_callback, port); status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { - err("%s - failed submitting write urb, error %d", __func__, status); + err("%s - failed submitting write urb, error %d", + __func__, status); count = status; goto error; } else { @@ -1635,7 +1683,7 @@ static int ftdi_write (struct usb_serial_port *port, error: usb_free_urb(urb); error_no_urb: - kfree (buffer); + kfree(buffer); error_no_buffer: spin_lock_irqsave(&priv->tx_lock, flags); priv->tx_outstanding_urbs--; @@ -1646,7 +1694,7 @@ error_no_buffer: /* This function may get called when the device is closed */ -static void ftdi_write_bulk_callback (struct urb *urb) +static void ftdi_write_bulk_callback(struct urb *urb) { unsigned long flags; struct usb_serial_port *port = urb->context; @@ -1656,7 +1704,7 @@ static void ftdi_write_bulk_callback (struct urb *urb) int status = urb->status; /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree (urb->transfer_buffer); + kfree(urb->transfer_buffer); dbg("%s - port %d", __func__, port->number); @@ -1686,8 +1734,9 @@ static void ftdi_write_bulk_callback (struct urb *urb) } /* ftdi_write_bulk_callback */ -static int ftdi_write_room( struct usb_serial_port *port ) +static int ftdi_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); int room; unsigned long flags; @@ -1707,11 +1756,11 @@ static int ftdi_write_room( struct usb_serial_port *port ) } spin_unlock_irqrestore(&priv->tx_lock, flags); return room; -} /* ftdi_write_room */ - +} -static int ftdi_chars_in_buffer (struct usb_serial_port *port) -{ /* ftdi_chars_in_buffer */ +static int ftdi_chars_in_buffer(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); int buffered; unsigned long flags; @@ -1726,12 +1775,10 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port) buffered = 0; } return buffered; -} /* ftdi_chars_in_buffer */ - - +} -static void ftdi_read_bulk_callback (struct urb *urb) -{ /* ftdi_read_bulk_callback */ +static void ftdi_read_bulk_callback(struct urb *urb) +{ struct usb_serial_port *port = urb->context; struct tty_struct *tty; struct ftdi_private *priv; @@ -1740,19 +1787,21 @@ static void ftdi_read_bulk_callback (struct urb *urb) int status = urb->status; if (urb->number_of_packets > 0) { - err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__, - urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets ); - err("%s transfer_flags %x ", __func__,urb->transfer_flags ); + err("%s transfer_buffer_length %d actual_length %d number of packets %d", + __func__, + urb->transfer_buffer_length, + urb->actual_length, urb->number_of_packets); + err("%s transfer_flags %x ", __func__, urb->transfer_flags); } dbg("%s - port %d", __func__, port->number); - if (port->open_count <= 0) + if (port->port.count <= 0) return; - tty = port->tty; + tty = port->port.tty; if (!tty) { - dbg("%s - bad tty pointer - exiting",__func__); + dbg("%s - bad tty pointer - exiting", __func__); return; } @@ -1762,14 +1811,13 @@ static void ftdi_read_bulk_callback (struct urb *urb) return; } - if (urb != port->read_urb) { + if (urb != port->read_urb) err("%s - Not my urb!", __func__); - } if (status) { - /* This will happen at close every time so it is a dbg not an err */ - dbg("(this is ok on close) nonzero read bulk status received: " - "%d", status); + /* This will happen at close every time so it is a dbg not an + err */ + dbg("(this is ok on close) nonzero read bulk status received: %d", status); return; } @@ -1785,7 +1833,7 @@ static void ftdi_read_bulk_callback (struct urb *urb) } /* ftdi_read_bulk_callback */ -static void ftdi_process_read (struct work_struct *work) +static void ftdi_process_read(struct work_struct *work) { /* ftdi_process_read */ struct ftdi_private *priv = container_of(work, struct ftdi_private, rx_work.work); @@ -1803,12 +1851,12 @@ static void ftdi_process_read (struct work_struct *work) dbg("%s - port %d", __func__, port->number); - if (port->open_count <= 0) + if (port->port.count <= 0) return; - tty = port->tty; + tty = port->port.tty; if (!tty) { - dbg("%s - bad tty pointer - exiting",__func__); + dbg("%s - bad tty pointer - exiting", __func__); return; } @@ -1832,11 +1880,11 @@ static void ftdi_process_read (struct work_struct *work) urb->actual_length - priv->rx_processed); } else { /* The first two bytes of every read packet are status */ - if (urb->actual_length > 2) { - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - } else { - dbg("Status only: %03oo %03oo",data[0],data[1]); - } + if (urb->actual_length > 2) + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); + else + dbg("Status only: %03oo %03oo", data[0], data[1]); } @@ -1846,16 +1894,19 @@ static void ftdi_process_read (struct work_struct *work) /* if CD is dropped and the line is not CLOCAL then we should hangup */ need_flip = 0; - for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) { + for (packet_offset = priv->rx_processed; + packet_offset < urb->actual_length; packet_offset += PKTSZ) { int length; - /* Compare new line status to the old one, signal if different */ - /* N.B. packet may be processed more than once, but differences - * are only processed once. */ + /* Compare new line status to the old one, signal if different/ + N.B. packet may be processed more than once, but differences + are only processed once. */ if (priv != NULL) { - char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK; + char new_status = data[packet_offset + 0] & + FTDI_STATUS_B0_MASK; if (new_status != priv->prev_status) { - priv->diff_status |= new_status ^ priv->prev_status; + priv->diff_status |= + new_status ^ priv->prev_status; wake_up_interruptible(&priv->delta_msr_wait); priv->prev_status = new_status; } @@ -1872,30 +1923,31 @@ static void ftdi_process_read (struct work_struct *work) break; } if (tty_buffer_request_room(tty, length) < length) { - /* break out & wait for throttling/unthrottling to happen */ + /* break out & wait for throttling/unthrottling to + happen */ dbg("%s - receive room low", __func__); break; } /* Handle errors and break */ error_flag = TTY_NORMAL; - /* Although the device uses a bitmask and hence can have multiple */ - /* errors on a packet - the order here sets the priority the */ - /* error is returned to the tty layer */ + /* Although the device uses a bitmask and hence can have + multiple errors on a packet - the order here sets the + priority the error is returned to the tty layer */ - if ( data[packet_offset+1] & FTDI_RS_OE ) { + if (data[packet_offset+1] & FTDI_RS_OE) { error_flag = TTY_OVERRUN; dbg("OVERRRUN error"); } - if ( data[packet_offset+1] & FTDI_RS_BI ) { + if (data[packet_offset+1] & FTDI_RS_BI) { error_flag = TTY_BREAK; dbg("BREAK received"); } - if ( data[packet_offset+1] & FTDI_RS_PE ) { + if (data[packet_offset+1] & FTDI_RS_PE) { error_flag = TTY_PARITY; dbg("PARITY error"); } - if ( data[packet_offset+1] & FTDI_RS_FE ) { + if (data[packet_offset+1] & FTDI_RS_FE) { error_flag = TTY_FRAME; dbg("FRAMING error"); } @@ -1904,7 +1956,8 @@ static void ftdi_process_read (struct work_struct *work) /* Note that the error flag is duplicated for every character received since we don't know which character it applied to */ - tty_insert_flip_char(tty, data[packet_offset+i], error_flag); + tty_insert_flip_char(tty, + data[packet_offset + i], error_flag); } need_flip = 1; } @@ -1912,19 +1965,19 @@ static void ftdi_process_read (struct work_struct *work) #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW /* if a parity error is detected you get status packets forever until a character is sent without a parity error. - This doesn't work well since the application receives a never - ending stream of bad data - even though new data hasn't been sent. - Therefore I (bill) have taken this out. + This doesn't work well since the application receives a + never ending stream of bad data - even though new data + hasn't been sent. Therefore I (bill) have taken this out. However - this might make sense for framing errors and so on so I am leaving the code in for now. */ else { - if (error_flag != TTY_NORMAL){ + if (error_flag != TTY_NORMAL) { dbg("error_flag is not normal"); - /* In this case it is just status - if that is an error send a bad character */ - if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + /* In this case it is just status - if that is + an error send a bad character */ + if (tty->flip.count >= TTY_FLIPBUF_SIZE) tty_flip_buffer_push(tty); - } tty_insert_flip_char(tty, 0xff, error_flag); need_flip = 1; } @@ -1933,9 +1986,8 @@ static void ftdi_process_read (struct work_struct *work) } /* "for(packet_offset=0..." */ /* Low latency */ - if (need_flip) { + if (need_flip) tty_flip_buffer_push(tty); - } if (packet_offset < urb->actual_length) { /* not completely processed - record progress */ @@ -1954,12 +2006,11 @@ static void ftdi_process_read (struct work_struct *work) } spin_unlock_irqrestore(&priv->rx_lock, flags); /* if the port is closed stop trying to read */ - if (port->open_count > 0){ + if (port->port.count > 0) /* delay processing of remainder */ schedule_delayed_work(&priv->rx_work, 1); - } else { + else dbg("%s - port is closed", __func__); - } return; } @@ -1967,24 +2018,26 @@ static void ftdi_process_read (struct work_struct *work) priv->rx_processed = 0; /* if the port is closed stop trying to read */ - if (port->open_count > 0){ + if (port->port.count > 0) { /* Continue trying to always read */ usb_fill_bulk_urb(port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, - ftdi_read_bulk_callback, port); + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ftdi_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", __func__, result); + err("%s - failed resubmitting read urb, error %d", + __func__, result); } - - return; } /* ftdi_process_read */ -static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) +static void ftdi_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); __u16 urb_value = 0; char buf[1]; @@ -1993,22 +2046,23 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) /* see drivers/char/tty_io.c to see it used */ /* last_set_data_urb_value NEVER has the break bit set in it */ - if (break_state) { + if (break_state) urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK; - } else { + else urb_value = priv->last_set_data_urb_value; - } - - if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), - FTDI_SIO_SET_DATA_REQUEST, - FTDI_SIO_SET_DATA_REQUEST_TYPE, - urb_value , priv->interface, - buf, 0, WDR_TIMEOUT) < 0) { - err("%s FAILED to enable/disable break state (state was %d)", __func__,break_state); + if (usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), + FTDI_SIO_SET_DATA_REQUEST, + FTDI_SIO_SET_DATA_REQUEST_TYPE, + urb_value , priv->interface, + buf, 0, WDR_TIMEOUT) < 0) { + err("%s FAILED to enable/disable break state (state was %d)", + __func__, break_state); } - dbg("%s break state is %d - urb is %d", __func__,break_state, urb_value); + dbg("%s break state is %d - urb is %d", __func__, + break_state, urb_value); } @@ -2018,26 +2072,28 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) * WARNING: set_termios calls this with old_termios in kernel space */ -static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) +static void ftdi_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { /* ftdi_termios */ struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); - struct ktermios *termios = port->tty->termios; + struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; __u16 urb_value; /* will hold the new flags */ char buf[1]; /* Perhaps I should dynamically alloc this? */ - // Added for xon/xoff support + /* Added for xon/xoff support */ unsigned int iflag = termios->c_iflag; unsigned char vstop; unsigned char vstart; dbg("%s", __func__); - /* Force baud rate if this device requires it, unless it is set to B0. */ + /* Force baud rate if this device requires it, unless it is set to + B0. */ if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) { dbg("%s: forcing baud rate for this device", __func__); - tty_encode_baud_rate(port->tty, priv->force_baud, + tty_encode_baud_rate(tty, priv->force_baud, priv->force_baud); } @@ -2053,8 +2109,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old not - so just do the change regardless - should be able to compare old_termios and tty->termios */ /* NOTE These routines can get interrupted by - ftdi_sio_read_bulk_callback - need to examine what this - means - don't see any problems yet */ + ftdi_sio_read_bulk_callback - need to examine what this means - + don't see any problems yet */ /* Set number of data bits, parity, stop bits */ @@ -2078,8 +2134,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old } } - /* This is needed by the break command since it uses the same command - but is - * or'ed with this value */ + /* This is needed by the break command since it uses the same command + - but is or'ed with this value */ priv->last_set_data_urb_value = urb_value; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -2091,7 +2147,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old } /* Now do the baudrate */ - if ((cflag & CBAUD) == B0 ) { + if ((cflag & CBAUD) == B0) { /* Disable flow control */ if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, @@ -2104,13 +2160,11 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { /* set the baudrate determined before */ - if (change_speed(port)) { + if (change_speed(tty, port)) err("%s urb failed to set baudrate", __func__); - } /* Ensure RTS and DTR are raised when baudrate changed from 0 */ - if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) { + if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) set_mctrl(port, TIOCM_DTR | TIOCM_RTS); - } } /* Set flow control */ @@ -2130,18 +2184,22 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old /* * Xon/Xoff code * - * Check the IXOFF status in the iflag component of the termios structure - * if IXOFF is not set, the pre-xon/xoff code is executed. - */ + * Check the IXOFF status in the iflag component of the + * termios structure. If IXOFF is not set, the pre-xon/xoff + * code is executed. + */ if (iflag & IXOFF) { - dbg("%s request to enable xonxoff iflag=%04x",__func__,iflag); - // Try to enable the XON/XOFF on the ftdi_sio - // Set the vstart and vstop -- could have been done up above where - // a lot of other dereferencing is done but that would be very - // inefficient as vstart and vstop are not always needed + dbg("%s request to enable xonxoff iflag=%04x", + __func__, iflag); + /* Try to enable the XON/XOFF on the ftdi_sio + * Set the vstart and vstop -- could have been done up + * above where a lot of other dereferencing is done but + * that would be very inefficient as vstart and vstop + * are not always needed. + */ vstart = termios->c_cc[VSTART]; vstop = termios->c_cc[VSTOP]; - urb_value=(vstop << 8) | (vstart); + urb_value = (vstop << 8) | (vstart); if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -2153,8 +2211,9 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old err("urb failed to set to xon/xoff flow control"); } } else { - /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */ - /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */ + /* else clause to only run if cflag ! CRTSCTS and iflag + * ! XOFF. CHECKME Assuming XON/XOFF handled by tty + * stack - not by device */ dbg("%s Turning off hardware flow control", __func__); if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -2168,11 +2227,11 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old } return; -} /* ftdi_termios */ - +} -static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) +static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned char buf[2]; int ret; @@ -2181,32 +2240,35 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) switch (priv->chip_type) { case SIO: /* Request the status from the device */ - if ((ret = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, 0, - buf, 1, WDR_TIMEOUT)) < 0 ) { + ret = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, 0, + buf, 1, WDR_TIMEOUT); + if (ret < 0) { err("%s Could not get modem status of device - err: %d", __func__, ret); - return(ret); + return ret; } break; case FT8U232AM: case FT232BM: case FT2232C: case FT232RL: - /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same - format as the data returned from the in point */ - if ((ret = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, priv->interface, - buf, 2, WDR_TIMEOUT)) < 0 ) { + /* the 8U232AM returns a two byte value (the sio is a 1 byte + value) - in the same format as the data returned from the in + point */ + ret = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, priv->interface, + buf, 2, WDR_TIMEOUT); + if (ret < 0) { err("%s Could not get modem status of device - err: %d", __func__, ret); - return(ret); + return ret; } break; default: @@ -2221,15 +2283,19 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) priv->last_dtr_rts; } -static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear) +static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; dbg("%s TIOCMSET", __func__); return update_mctrl(port, set, clear); } -static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +static int ftdi_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); dbg("%s cmd 0x%04x", __func__, cmd); @@ -2238,10 +2304,12 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne switch (cmd) { case TIOCGSERIAL: /* gets serial port data */ - return get_serial_info(port, (struct serial_struct __user *) arg); + return get_serial_info(port, + (struct serial_struct __user *) arg); case TIOCSSERIAL: /* sets serial port data */ - return set_serial_info(port, (struct serial_struct __user *) arg); + return set_serial_info(tty, port, + (struct serial_struct __user *) arg); /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change @@ -2260,45 +2328,41 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne else { char diff = priv->diff_status; - if (diff == 0) { + if (diff == 0) return -EIO; /* no change => error */ - } /* Consume all events */ priv->diff_status = 0; - /* Return 0 if caller wanted to know about these bits */ - if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) || - ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) || - ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) || - ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) { + /* Return 0 if caller wanted to know about + these bits */ + if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) || + ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) || + ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) || + ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) { return 0; } /* - * Otherwise caller can't care less about what happened, - * and so we continue to wait for more events. + * Otherwise caller can't care less about what + * happened,and so we continue to wait for more + * events. */ } } - return(0); - break; + return 0; default: break; - } - - - /* This is not necessarily an error - turns out the higher layers will do - * some ioctls itself (see comment above) + /* This is not necessarily an error - turns out the higher layers + * will do some ioctls themselves (see comment above) */ dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd); + return -ENOIOCTLCMD; +} - return(-ENOIOCTLCMD); -} /* ftdi_ioctl */ - - -static void ftdi_throttle (struct usb_serial_port *port) +static void ftdi_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -2310,8 +2374,9 @@ static void ftdi_throttle (struct usb_serial_port *port) } -static void ftdi_unthrottle (struct usb_serial_port *port) +static void ftdi_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); int actually_throttled; unsigned long flags; @@ -2327,7 +2392,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port) schedule_delayed_work(&priv->rx_work, 0); } -static int __init ftdi_init (void) +static int __init ftdi_init(void) { int retval; @@ -2357,13 +2422,13 @@ failed_sio_register: } -static void __exit ftdi_exit (void) +static void __exit ftdi_exit(void) { dbg("%s", __func__); - usb_deregister (&ftdi_driver); - usb_serial_deregister (&ftdi_sio_device); + usb_deregister(&ftdi_driver); + usb_serial_deregister(&ftdi_sio_device); } @@ -2371,8 +2436,8 @@ static void __exit ftdi_exit (void) module_init(ftdi_init); module_exit(ftdi_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 8302eca893ea..a577ea44dcf9 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -1,20 +1,20 @@ /* - * Definitions for the FTDI USB Single Port Serial Converter - - * known as FTDI_SIO (Serial Input/Output application of the chipset) + * Definitions for the FTDI USB Single Port Serial Converter - + * known as FTDI_SIO (Serial Input/Output application of the chipset) * * The example I have is known as the USC-1000 which is available from * http://www.dse.co.nz - cat no XH4214 It looks similar to this: * http://www.dansdata.com/usbser.htm but I can't be sure There are other * USC-1000s which don't look like my device though so beware! * - * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, + * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, * USB on the other. * * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details * of the protocol required to talk to the device and ongoing assistence * during development. * - * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the + * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the * FTDI_SIO implementation. * * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais @@ -472,7 +472,7 @@ /* * DSS-20 Sync Station for Sony Ericsson P800 */ -#define FTDI_DSS20_PID 0xFC82 +#define FTDI_DSS20_PID 0xFC82 /* * Home Electronics (www.home-electro.com) USB gadgets @@ -884,7 +884,7 @@ /* * BmRequestType: 0100 0000B * bRequest: FTDI_SIO_RESET - * wValue: Control Value + * wValue: Control Value * 0 = Reset SIO * 1 = Purge RX buffer * 2 = Purge TX buffer @@ -952,7 +952,7 @@ * 101 - add .625 to divisor * 110 - add .750 to divisor * 111 - add .875 to divisor - * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is + * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is * placed in bit 0 of the urb index. * * Note that there are a couple of special cases to support the highest baud @@ -971,8 +971,8 @@ typedef enum { } ftdi_chip_type_t; typedef enum { - ftdi_sio_b300 = 0, - ftdi_sio_b600 = 1, + ftdi_sio_b300 = 0, + ftdi_sio_b600 = 1, ftdi_sio_b1200 = 2, ftdi_sio_b2400 = 3, ftdi_sio_b4800 = 4, @@ -981,7 +981,7 @@ typedef enum { ftdi_sio_b38400 = 7, ftdi_sio_b57600 = 8, ftdi_sio_b115200 = 9 -} FTDI_SIO_baudrate_t ; +} FTDI_SIO_baudrate_t; /* * The ftdi_8U232AM_xxMHz_byyy constants have been removed. The encoded divisor values @@ -990,19 +990,19 @@ typedef enum { #define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA #define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40 -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 ) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 ) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 ) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 ) +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) #define FTDI_SIO_SET_BREAK (0x1 << 14) /* FTDI_SIO_SET_DATA */ /* - * BmRequestType: 0100 0000B + * BmRequestType: 0100 0000B * bRequest: FTDI_SIO_SET_DATA * wValue: Data characteristics (see below) * wIndex: Port @@ -1035,7 +1035,7 @@ typedef enum { #define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40 #define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL -/* +/* * BmRequestType: 0100 0000B * bRequest: FTDI_SIO_MODEM_CTRL * wValue: ControlValue (see below) @@ -1049,11 +1049,11 @@ typedef enum { */ #define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_HIGH (1 | (FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_LOW (0 | (FTDI_SIO_SET_DTR_MASK << 8)) #define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) -#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) +#define FTDI_SIO_SET_RTS_HIGH (2 | (FTDI_SIO_SET_RTS_MASK << 8)) +#define FTDI_SIO_SET_RTS_LOW (0 | (FTDI_SIO_SET_RTS_MASK << 8)) /* * ControlValue @@ -1076,7 +1076,7 @@ typedef enum { /* FTDI_SIO_SET_FLOW_CTRL */ #define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40 #define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 #define FTDI_SIO_RTS_CTS_HS (0x1 << 8) #define FTDI_SIO_DTR_DSR_HS (0x2 << 8) #define FTDI_SIO_XON_XOFF_HS (0x4 << 8) @@ -1085,7 +1085,7 @@ typedef enum { * bRequest: FTDI_SIO_SET_FLOW_CTRL * wValue: Xoff/Xon * wIndex: Protocol/Port - hIndex is protocl / lIndex is port - * wLength: 0 + * wLength: 0 * Data: None * * hIndex protocol is: @@ -1101,10 +1101,10 @@ typedef enum { * * A value of zero in the hIndex field disables handshaking * - * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character + * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character * and the lValue field contains the XON character. - */ - + */ + /* * FTDI_SIO_GET_LATENCY_TIMER * @@ -1118,7 +1118,7 @@ typedef enum { #define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER #define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0 -/* +/* * BmRequestType: 1100 0000b * bRequest: FTDI_SIO_GET_LATENCY_TIMER * wValue: 0 @@ -1127,7 +1127,7 @@ typedef enum { * Data: latency (on return) */ -/* +/* * FTDI_SIO_SET_LATENCY_TIMER * * Set the timeout interval. The FTDI collects data from the slave @@ -1140,7 +1140,7 @@ typedef enum { #define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER #define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40 -/* +/* * BmRequestType: 0100 0000b * bRequest: FTDI_SIO_SET_LATENCY_TIMER * wValue: Latency (milliseconds) @@ -1155,7 +1155,7 @@ typedef enum { */ /* - * FTDI_SIO_SET_EVENT_CHAR + * FTDI_SIO_SET_EVENT_CHAR * * Set the special event character for the specified communications port. * If the device sees this character it will immediately return the @@ -1168,7 +1168,7 @@ typedef enum { #define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40 -/* +/* * BmRequestType: 0100 0000b * bRequest: FTDI_SIO_SET_EVENT_CHAR * wValue: EventChar @@ -1184,12 +1184,12 @@ typedef enum { * B9..15 Reserved * */ - + /* FTDI_SIO_SET_ERROR_CHAR */ /* Set the parity error replacement character for the specified communications port */ -/* +/* * BmRequestType: 0100 0000b * bRequest: FTDI_SIO_SET_EVENT_CHAR * wValue: Error Char @@ -1215,15 +1215,15 @@ typedef enum { #define FTDI_SIO_DSR_MASK 0x20 #define FTDI_SIO_RI_MASK 0x40 #define FTDI_SIO_RLSD_MASK 0x80 -/* +/* * BmRequestType: 1100 0000b * bRequest: FTDI_SIO_GET_MODEM_STATUS * wValue: zero * wIndex: Port * wLength: 1 * Data: Status - * - * One byte of data is returned + * + * One byte of data is returned * B0..3 0 * B4 CTS * 0 = inactive @@ -1236,15 +1236,15 @@ typedef enum { * 1 = active * B7 Receive Line Signal Detect (RLSD) * 0 = inactive - * 1 = active + * 1 = active */ -/* Descriptors returned by the device - * +/* Descriptors returned by the device + * * Device Descriptor - * + * * Offset Field Size Value Description * 0 bLength 1 0x12 Size of descriptor in bytes * 1 bDescriptorType 1 0x01 DEVICE Descriptor Type @@ -1260,9 +1260,9 @@ typedef enum { * 15 iProduct 1 0x02 Index of prod string desc * 16 iSerialNumber 1 0x02 Index of serial nmr string desc * 17 bNumConfigurations 1 0x01 Number of possible configurations - * + * * Configuration Descriptor - * + * * Offset Field Size Value * 0 bLength 1 0x09 Size of descriptor in bytes * 1 bDescriptorType 1 0x02 CONFIGURATION Descriptor Type @@ -1272,9 +1272,9 @@ typedef enum { * 6 iConfiguration 1 0x02 Index of config string descriptor * 7 bmAttributes 1 0x20 Config characteristics Remote Wakeup * 8 MaxPower 1 0x1E Max power consumption - * + * * Interface Descriptor - * + * * Offset Field Size Value * 0 bLength 1 0x09 Size of descriptor in bytes * 1 bDescriptorType 1 0x04 INTERFACE Descriptor Type @@ -1285,9 +1285,9 @@ typedef enum { * 6 bInterfaceSubClass 1 0xFF Subclass Code * 7 bInterfaceProtocol 1 0xFF Protocol Code * 8 iInterface 1 0x02 Index of interface string description - * + * * IN Endpoint Descriptor - * + * * Offset Field Size Value * 0 bLength 1 0x07 Size of descriptor in bytes * 1 bDescriptorType 1 0x05 ENDPOINT descriptor type @@ -1295,9 +1295,9 @@ typedef enum { * 3 bmAttributes 1 0x02 Endpoint attributes - Bulk * 4 bNumEndpoints 2 0x0040 maximum packet size * 5 bInterval 1 0x00 Interval for polling endpoint - * + * * OUT Endpoint Descriptor - * + * * Offset Field Size Value * 0 bLength 1 0x07 Size of descriptor in bytes * 1 bDescriptorType 1 0x05 ENDPOINT descriptor type @@ -1305,17 +1305,17 @@ typedef enum { * 3 bmAttributes 1 0x02 Endpoint attributes - Bulk * 4 bNumEndpoints 2 0x0040 maximum packet size * 5 bInterval 1 0x00 Interval for polling endpoint - * + * * DATA FORMAT - * + * * IN Endpoint - * + * * The device reserves the first two bytes of data on this endpoint to contain the current * values of the modem and line status registers. In the absence of data, the device * generates a message consisting of these two status bytes every 40 ms - * + * * Byte 0: Modem Status - * + * * Offset Description * B0 Reserved - must be 1 * B1 Reserved - must be 0 @@ -1325,9 +1325,9 @@ typedef enum { * B5 Data Set Ready (DSR) * B6 Ring Indicator (RI) * B7 Receive Line Signal Detect (RLSD) - * + * * Byte 1: Line Status - * + * * Offset Description * B0 Data Ready (DR) * B1 Overrun Error (OE) @@ -1337,7 +1337,7 @@ typedef enum { * B5 Transmitter Holding Register (THRE) * B6 Transmitter Empty (TEMT) * B7 Error in RCVR FIFO - * + * */ #define FTDI_RS0_CTS (1 << 4) #define FTDI_RS0_DSR (1 << 5) @@ -1355,17 +1355,17 @@ typedef enum { /* * OUT Endpoint - * + * * This device reserves the first bytes of data on this endpoint contain the length * and port identifier of the message. For the FTDI USB Serial converter the port * identifier is always 1. - * + * * Byte 0: Line Status - * + * * Offset Description * B0 Reserved - must be 1 * B1 Reserved - must be 0 * B2..7 Length of message - (not including Byte 0) - * + * */ diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c index e8ba2cb5995d..d30f736d2cc5 100644 --- a/drivers/usb/serial/funsoft.c +++ b/drivers/usb/serial/funsoft.c @@ -14,7 +14,7 @@ #include <linux/module.h> #include <linux/usb.h> #include <linux/usb/serial.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> static int debug; diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 8ce5a56a48e3..2e663f1afd5e 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -33,7 +33,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/atomic.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -44,7 +44,7 @@ static int initial_mode = 1; /* debug flag */ -static int debug = 0; +static int debug; #define GARMIN_VENDOR_ID 0x091E @@ -56,7 +56,7 @@ static int debug = 0; #define VERSION_MINOR 31 #define _STR(s) #s -#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b) +#define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b) #define DRIVER_VERSION _DRIVER_VERSION(VERSION_MAJOR, VERSION_MINOR) #define DRIVER_AUTHOR "hermann kneissel" #define DRIVER_DESC "garmin gps driver" @@ -65,37 +65,37 @@ static int debug = 0; #define EINVPKT 1000 /* invalid packet structure */ -// size of the header of a packet using the usb protocol +/* size of the header of a packet using the usb protocol */ #define GARMIN_PKTHDR_LENGTH 12 -// max. possible size of a packet using the serial protocol -#define MAX_SERIAL_PKT_SIZ (3+255+3) +/* max. possible size of a packet using the serial protocol */ +#define MAX_SERIAL_PKT_SIZ (3 + 255 + 3) -// max. possible size of a packet with worst case stuffing -#define MAX_SERIAL_PKT_SIZ_STUFFED MAX_SERIAL_PKT_SIZ+256 +/* max. possible size of a packet with worst case stuffing */ +#define MAX_SERIAL_PKT_SIZ_STUFFED (MAX_SERIAL_PKT_SIZ + 256) -// size of a buffer able to hold a complete (no stuffing) packet -// (the document protocol does not contain packets with a larger -// size, but in theory a packet may be 64k+12 bytes - if in -// later protocol versions larger packet sizes occur, this value -// should be increased accordingly, so the input buffer is always -// large enough the store a complete packet inclusive header) -#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ) +/* size of a buffer able to hold a complete (no stuffing) packet + * (the document protocol does not contain packets with a larger + * size, but in theory a packet may be 64k+12 bytes - if in + * later protocol versions larger packet sizes occur, this value + * should be increased accordingly, so the input buffer is always + * large enough the store a complete packet inclusive header) */ +#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ) -// size of a buffer able to hold a complete (incl. stuffing) packet -#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED) +/* size of a buffer able to hold a complete (incl. stuffing) packet */ +#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED) -// where to place the packet id of a serial packet, so we can -// prepend the usb-packet header without the need to move the -// packets data +/* where to place the packet id of a serial packet, so we can + * prepend the usb-packet header without the need to move the + * packets data */ #define GSP_INITIAL_OFFSET (GARMIN_PKTHDR_LENGTH-2) -// max. size of incoming private packets (header+1 param) +/* max. size of incoming private packets (header+1 param) */ #define PRIVPKTSIZ (GARMIN_PKTHDR_LENGTH+4) #define GARMIN_LAYERID_TRANSPORT 0 #define GARMIN_LAYERID_APPL 20 -// our own layer-id to use for some control mechanisms +/* our own layer-id to use for some control mechanisms */ #define GARMIN_LAYERID_PRIVATE 0x01106E4B #define GARMIN_PKTID_PVT_DATA 51 @@ -103,7 +103,7 @@ static int debug = 0; #define CMND_ABORT_TRANSFER 0 -// packet ids used in private layer +/* packet ids used in private layer */ #define PRIV_PKTID_SET_DEBUG 1 #define PRIV_PKTID_SET_MODE 2 #define PRIV_PKTID_INFO_REQ 3 @@ -121,7 +121,8 @@ static int debug = 0; struct garmin_packet { struct list_head list; int seq; - int size; // the real size of the data array, always > 0 + /* the real size of the data array, always > 0 */ + int size; __u8 data[1]; }; @@ -164,7 +165,7 @@ struct garmin_data { #define MODE_NATIVE 0 #define MODE_GARMIN_SERIAL 1 -// Flags used in garmin_data.flags: +/* Flags used in garmin_data.flags: */ #define FLAGS_SESSION_REPLY_MASK 0x00C0 #define FLAGS_SESSION_REPLY1_SEEN 0x0080 #define FLAGS_SESSION_REPLY2_SEEN 0x0040 @@ -185,7 +186,7 @@ struct garmin_data { /* function prototypes */ -static void gsp_next_packet(struct garmin_data * garmin_data_p); +static void gsp_next_packet(struct garmin_data *garmin_data_p); static int garmin_write_bulk(struct usb_serial_port *port, const unsigned char *buf, int count, int dismiss_ack); @@ -217,12 +218,13 @@ static unsigned char const PRIVATE_REQ[] static struct usb_device_id id_table [] = { - /* the same device id seems to be used by all usb enabled gps devices */ - { USB_DEVICE(GARMIN_VENDOR_ID, 3 ) }, + /* the same device id seems to be used by all + usb enabled GPS devices */ + { USB_DEVICE(GARMIN_VENDOR_ID, 3) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver garmin_driver = { .name = "garmin_gps", @@ -233,9 +235,10 @@ static struct usb_driver garmin_driver = { }; -static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p) +static inline int noResponseFromAppLayer(struct garmin_data *garmin_data_p) { - return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count); + return atomic_read(&garmin_data_p->req_count) == + atomic_read(&garmin_data_p->resp_count); } @@ -261,10 +264,10 @@ static inline int getDataLength(const __u8 *usbPacket) */ static inline int isAbortTrfCmnd(const unsigned char *buf) { - if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ, - sizeof(GARMIN_STOP_TRANSFER_REQ)) || - 0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2, - sizeof(GARMIN_STOP_TRANSFER_REQ_V2))) + if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ, + sizeof(GARMIN_STOP_TRANSFER_REQ)) || + 0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2, + sizeof(GARMIN_STOP_TRANSFER_REQ_V2))) return 1; else return 0; @@ -275,11 +278,11 @@ static inline int isAbortTrfCmnd(const unsigned char *buf) static void send_to_tty(struct usb_serial_port *port, char *data, unsigned int actual_length) { - struct tty_struct *tty = port->tty; + struct tty_struct *tty = port->port.tty; if (tty && actual_length) { - usb_serial_debug_data(debug, &port->dev, + usb_serial_debug_data(debug, &port->dev, __func__, actual_length, data); tty_buffer_request_room(tty, actual_length); @@ -296,7 +299,7 @@ static void send_to_tty(struct usb_serial_port *port, /* * queue a received (usb-)packet for later processing */ -static int pkt_add(struct garmin_data * garmin_data_p, +static int pkt_add(struct garmin_data *garmin_data_p, unsigned char *data, unsigned int data_length) { int state = 0; @@ -307,7 +310,7 @@ static int pkt_add(struct garmin_data * garmin_data_p, /* process only packets containg data ... */ if (data_length) { pkt = kmalloc(sizeof(struct garmin_packet)+data_length, - GFP_ATOMIC); + GFP_ATOMIC); if (pkt == NULL) { dev_err(&garmin_data_p->port->dev, "out of memory\n"); return 0; @@ -325,16 +328,15 @@ static int pkt_add(struct garmin_data * garmin_data_p, /* in serial mode, if someone is waiting for data from the device, iconvert and send the next packet to tty. */ - if (result && (state == STATE_GSP_WAIT_DATA)) { + if (result && (state == STATE_GSP_WAIT_DATA)) gsp_next_packet(garmin_data_p); - } } return result; } /* get the next pending packet */ -static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p) +static struct garmin_packet *pkt_pop(struct garmin_data *garmin_data_p) { unsigned long flags; struct garmin_packet *result = NULL; @@ -350,7 +352,7 @@ static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p) /* free up all queued data */ -static void pkt_clear(struct garmin_data * garmin_data_p) +static void pkt_clear(struct garmin_data *garmin_data_p) { unsigned long flags; struct garmin_packet *result = NULL; @@ -372,7 +374,7 @@ static void pkt_clear(struct garmin_data * garmin_data_p) ******************************************************************************/ /* send an ack packet back to the tty */ -static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) +static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id) { __u8 pkt[10]; __u8 cksum = 0; @@ -391,9 +393,8 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) *ptr++ = pkt_id; cksum += pkt_id; - if (pkt_id == DLE) { + if (pkt_id == DLE) *ptr++ = DLE; - } *ptr++ = 0; *ptr++ = 0xFF & (-cksum); @@ -415,12 +416,12 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) * at GSP_INITIAL_OFFSET. * * count - number of bytes in the input buffer including space reserved for - * the usb header: GSP_INITIAL_OFFSET + number of bytes in packet + * the usb header: GSP_INITIAL_OFFSET + number of bytes in packet * (including pkt-id, data-length a. cksum) */ -static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) +static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) { - const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; + const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; int cksum = 0; @@ -440,8 +441,8 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) cksum += *recpkt++; cksum += *recpkt++; - // sanity check, remove after test ... - if ((__u8*)&(usbdata[3]) != recpkt) { + /* sanity check, remove after test ... */ + if ((__u8 *)&(usbdata[3]) != recpkt) { dbg("%s - ptr mismatch %p - %p", __func__, &(usbdata[4]), recpkt); return -EINVPKT; @@ -462,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) usbdata[1] = __cpu_to_le32(pktid); usbdata[2] = __cpu_to_le32(size); - garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer, + garmin_write_bulk(garmin_data_p->port, garmin_data_p->inbuffer, GARMIN_PKTHDR_LENGTH+size, 0); /* if this was an abort-transfer command, flush all @@ -495,7 +496,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) * if the input is an abort command, drop all queued data. */ -static int gsp_receive(struct garmin_data * garmin_data_p, +static int gsp_receive(struct garmin_data *garmin_data_p, const unsigned char *buf, int count) { unsigned long flags; @@ -504,10 +505,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p, int i = 0; __u8 *dest; int size; - // dleSeen: set if last byte read was a DLE + /* dleSeen: set if last byte read was a DLE */ int dleSeen; - // skip: if set, skip incoming data until possible start of - // new packet + /* skip: if set, skip incoming data until possible start of + * new packet + */ int skip; __u8 data; @@ -521,14 +523,13 @@ static int gsp_receive(struct garmin_data * garmin_data_p, dbg("%s - dle=%d skip=%d size=%d count=%d", __func__, dleSeen, skip, size, count); - if (size == 0) { + if (size == 0) size = GSP_INITIAL_OFFSET; - } while (offs < count) { data = *(buf+offs); - offs ++; + offs++; if (data == DLE) { if (skip) { /* start of a new pkt */ @@ -554,9 +555,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p, ack_or_nak_seen = NAK; dbg("NAK packet complete."); } else { - dbg("packet complete " - "- id=0x%X.", - 0xFF & data); + dbg("packet complete - id=0x%X.", + 0xFF & data); gsp_rec_packet(garmin_data_p, size); } @@ -589,7 +589,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p, garmin_data_p->insize = size; - // copy flags back to structure + /* copy flags back to structure */ if (skip) garmin_data_p->flags |= FLAGS_GSP_SKIP; else @@ -600,16 +600,13 @@ static int gsp_receive(struct garmin_data * garmin_data_p, else garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN; - if (ack_or_nak_seen) { + if (ack_or_nak_seen) garmin_data_p->state = STATE_GSP_WAIT_DATA; - } spin_unlock_irqrestore(&garmin_data_p->lock, flags); - if (ack_or_nak_seen) { + if (ack_or_nak_seen) gsp_next_packet(garmin_data_p); - } - return count; } @@ -623,7 +620,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p, * * return <0 on error, 0 if packet is incomplete or > 0 if packet was sent */ -static int gsp_send(struct garmin_data * garmin_data_p, +static int gsp_send(struct garmin_data *garmin_data_p, const unsigned char *buf, int count) { const unsigned char *src; @@ -631,11 +628,11 @@ static int gsp_send(struct garmin_data * garmin_data_p, int pktid = 0; int datalen = 0; int cksum = 0; - int i=0; + int i = 0; int k; dbg("%s - state %d - %d bytes.", __func__, - garmin_data_p->state, count); + garmin_data_p->state, count); k = garmin_data_p->outsize; if ((k+count) > GPS_OUT_BUFSIZ) { @@ -650,7 +647,7 @@ static int gsp_send(struct garmin_data * garmin_data_p, if (k >= GARMIN_PKTHDR_LENGTH) { pktid = getPacketId(garmin_data_p->outbuffer); - datalen= getDataLength(garmin_data_p->outbuffer); + datalen = getDataLength(garmin_data_p->outbuffer); i = GARMIN_PKTHDR_LENGTH + datalen; if (k < i) return 0; @@ -658,19 +655,18 @@ static int gsp_send(struct garmin_data * garmin_data_p, return 0; } - dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__, - k, i); + dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__, k, i); /* garmin_data_p->outbuffer now contains a complete packet */ usb_serial_debug_data(debug, &garmin_data_p->port->dev, - __func__, k, garmin_data_p->outbuffer); + __func__, k, garmin_data_p->outbuffer); garmin_data_p->outsize = 0; if (GARMIN_LAYERID_APPL != getLayerId(garmin_data_p->outbuffer)) { - dbg("not an application packet (%d)", - getLayerId(garmin_data_p->outbuffer)); + dbg("not an application packet (%d)", + getLayerId(garmin_data_p->outbuffer)); return -1; } @@ -688,14 +684,14 @@ static int gsp_send(struct garmin_data * garmin_data_p, k = 0; src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH; - for (i=0; i<datalen; i++) { + for (i = 0; i < datalen; i++) { if (*src++ == DLE) k++; } src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH; if (k > (GARMIN_PKTHDR_LENGTH-2)) { - /* can't add stuffing DLEs in place, move data to end + /* can't add stuffing DLEs in place, move data to end of buffer ... */ dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen; memcpy(dst, src, datalen); @@ -712,14 +708,14 @@ static int gsp_send(struct garmin_data * garmin_data_p, if (datalen == DLE) *dst++ = DLE; - for (i=0; i<datalen; i++) { + for (i = 0; i < datalen; i++) { __u8 c = *src++; *dst++ = c; cksum += c; if (c == DLE) *dst++ = DLE; } - + cksum = 0xFF & -cksum; *dst++ = cksum; if (cksum == DLE) @@ -744,7 +740,7 @@ static int gsp_send(struct garmin_data * garmin_data_p, /* * Process the next pending data packet - if there is one */ -static void gsp_next_packet(struct garmin_data * garmin_data_p) +static void gsp_next_packet(struct garmin_data *garmin_data_p) { struct garmin_packet *pkt = NULL; @@ -774,17 +770,17 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p) * buf contains the data read, it may span more than one packet * or even incomplete packets */ -static int nat_receive(struct garmin_data * garmin_data_p, +static int nat_receive(struct garmin_data *garmin_data_p, const unsigned char *buf, int count) { unsigned long flags; - __u8 * dest; + __u8 *dest; int offs = 0; int result = count; int len; while (offs < count) { - // if buffer contains header, copy rest of data + /* if buffer contains header, copy rest of data */ if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH) len = GARMIN_PKTHDR_LENGTH +getDataLength(garmin_data_p->inbuffer); @@ -792,9 +788,9 @@ static int nat_receive(struct garmin_data * garmin_data_p, len = GARMIN_PKTHDR_LENGTH; if (len >= GPS_IN_BUFSIZ) { - /* seem to be an invalid packet, ignore rest of input */ - dbg("%s - packet size too large: %d", - __func__, len); + /* seems to be an invalid packet, ignore rest + of input */ + dbg("%s - packet size too large: %d", __func__, len); garmin_data_p->insize = 0; count = 0; result = -EINVPKT; @@ -804,7 +800,7 @@ static int nat_receive(struct garmin_data * garmin_data_p, len = (count-offs); if (len > 0) { dest = garmin_data_p->inbuffer - +garmin_data_p->insize; + + garmin_data_p->insize; memcpy(dest, buf+offs, len); garmin_data_p->insize += len; offs += len; @@ -816,17 +812,19 @@ static int nat_receive(struct garmin_data * garmin_data_p, len = GARMIN_PKTHDR_LENGTH+ getDataLength(garmin_data_p->inbuffer); if (garmin_data_p->insize >= len) { - garmin_write_bulk (garmin_data_p->port, - garmin_data_p->inbuffer, - len, 0); + garmin_write_bulk(garmin_data_p->port, + garmin_data_p->inbuffer, + len, 0); garmin_data_p->insize = 0; /* if this was an abort-transfer command, flush all queued data. */ if (isAbortTrfCmnd(garmin_data_p->inbuffer)) { - spin_lock_irqsave(&garmin_data_p->lock, flags); + spin_lock_irqsave(&garmin_data_p->lock, + flags); garmin_data_p->flags |= FLAGS_DROP_DATA; - spin_unlock_irqrestore(&garmin_data_p->lock, flags); + spin_unlock_irqrestore( + &garmin_data_p->lock, flags); pkt_clear(garmin_data_p); } } @@ -842,7 +840,7 @@ static int nat_receive(struct garmin_data * garmin_data_p, static void priv_status_resp(struct usb_serial_port *port) { - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); __le32 *pkt = (__le32 *)garmin_data_p->privpkt; pkt[0] = __cpu_to_le32(GARMIN_LAYERID_PRIVATE); @@ -852,7 +850,7 @@ static void priv_status_resp(struct usb_serial_port *port) pkt[4] = __cpu_to_le32(garmin_data_p->mode); pkt[5] = __cpu_to_le32(garmin_data_p->serial_num); - send_to_tty(port, (__u8*)pkt, 6*4); + send_to_tty(port, (__u8 *)pkt, 6 * 4); } @@ -864,7 +862,7 @@ static int process_resetdev_request(struct usb_serial_port *port) { unsigned long flags; int status; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED); @@ -872,8 +870,8 @@ static int process_resetdev_request(struct usb_serial_port *port) garmin_data_p->serial_num = 0; spin_unlock_irqrestore(&garmin_data_p->lock, flags); - usb_kill_urb (port->interrupt_in_urb); - dbg("%s - usb_reset_device", __func__ ); + usb_kill_urb(port->interrupt_in_urb); + dbg("%s - usb_reset_device", __func__); status = usb_reset_device(port->serial->dev); if (status) dbg("%s - usb_reset_device failed: %d", @@ -886,7 +884,7 @@ static int process_resetdev_request(struct usb_serial_port *port) /* * clear all cached data */ -static int garmin_clear(struct garmin_data * garmin_data_p) +static int garmin_clear(struct garmin_data *garmin_data_p) { unsigned long flags; int status = 0; @@ -896,8 +894,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p) if (port != NULL && atomic_read(&garmin_data_p->resp_count)) { /* send a terminate command */ status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ, - sizeof(GARMIN_STOP_TRANSFER_REQ), - 1); + sizeof(GARMIN_STOP_TRANSFER_REQ), 1); } /* flush all queued data */ @@ -920,28 +917,26 @@ static int garmin_init_session(struct usb_serial_port *port) { unsigned long flags; struct usb_serial *serial = port->serial; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); int status = 0; if (status == 0) { - usb_kill_urb (port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); dbg("%s - adding interrupt input", __func__); port->interrupt_in_urb->dev = serial->dev; status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (status) dev_err(&serial->dev->dev, - "%s - failed submitting interrupt urb," - " error %d\n", - __func__, status); + "%s - failed submitting interrupt urb, error %d\n", + __func__, status); } if (status == 0) { dbg("%s - starting session ...", __func__); garmin_data_p->state = STATE_ACTIVE; status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ, - sizeof(GARMIN_START_SESSION_REQ), - 0); + sizeof(GARMIN_START_SESSION_REQ), 0); if (status >= 0) { @@ -951,14 +946,14 @@ static int garmin_init_session(struct usb_serial_port *port) /* not needed, but the win32 driver does it too ... */ status = garmin_write_bulk(port, - GARMIN_START_SESSION_REQ2, - sizeof(GARMIN_START_SESSION_REQ2), - 0); + GARMIN_START_SESSION_REQ2, + sizeof(GARMIN_START_SESSION_REQ2), 0); if (status >= 0) { status = 0; spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->ignorePkts++; - spin_unlock_irqrestore(&garmin_data_p->lock, flags); + spin_unlock_irqrestore(&garmin_data_p->lock, + flags); } } } @@ -970,11 +965,12 @@ static int garmin_init_session(struct usb_serial_port *port) -static int garmin_open (struct usb_serial_port *port, struct file *filp) +static int garmin_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { unsigned long flags; int status = 0; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); dbg("%s - port %d", __func__, port->number); @@ -983,8 +979,8 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp) * through, otherwise it is scheduled, and with high data rates (like * with OHCI) data can get lost. */ - if (port->tty) - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->mode = initial_mode; @@ -995,23 +991,22 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp) spin_unlock_irqrestore(&garmin_data_p->lock, flags); /* shutdown any bulk reads that might be going on */ - usb_kill_urb (port->write_urb); - usb_kill_urb (port->read_urb); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); - if (garmin_data_p->state == STATE_RESET) { + if (garmin_data_p->state == STATE_RESET) status = garmin_init_session(port); - } garmin_data_p->state = STATE_ACTIVE; - return status; } -static void garmin_close (struct usb_serial_port *port, struct file * filp) +static void garmin_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__, port->number, garmin_data_p->mode, @@ -1025,8 +1020,8 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp) garmin_clear(garmin_data_p); /* shutdown our urbs */ - usb_kill_urb (port->read_urb); - usb_kill_urb (port->write_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->write_urb); if (!port->serial->disconnected) { if (noResponseFromAppLayer(garmin_data_p) || @@ -1042,21 +1037,22 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp) mutex_unlock(&port->serial->disc_mutex); } - -static void garmin_write_bulk_callback (struct urb *urb) +static void garmin_write_bulk_callback(struct urb *urb) { unsigned long flags; struct usb_serial_port *port = urb->context; int status = urb->status; if (port) { - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = + usb_get_serial_port_data(port); dbg("%s - port %d", __func__, port->number); if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer) && (garmin_data_p->mode == MODE_GARMIN_SERIAL)) { - gsp_send_ack(garmin_data_p, ((__u8 *)urb->transfer_buffer)[4]); + gsp_send_ack(garmin_data_p, + ((__u8 *)urb->transfer_buffer)[4]); } if (status) { @@ -1070,20 +1066,21 @@ static void garmin_write_bulk_callback (struct urb *urb) usb_serial_port_softint(port); } - /* Ignore errors that resulted from garmin_write_bulk with dismiss_ack=1 */ + /* Ignore errors that resulted from garmin_write_bulk with + dismiss_ack = 1 */ /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree (urb->transfer_buffer); + kfree(urb->transfer_buffer); } -static int garmin_write_bulk (struct usb_serial_port *port, +static int garmin_write_bulk(struct usb_serial_port *port, const unsigned char *buf, int count, int dismiss_ack) { unsigned long flags; struct usb_serial *serial = port->serial; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); struct urb *urb; unsigned char *buffer; int status; @@ -1095,7 +1092,7 @@ static int garmin_write_bulk (struct usb_serial_port *port, garmin_data_p->flags &= ~FLAGS_DROP_DATA; spin_unlock_irqrestore(&garmin_data_p->lock, flags); - buffer = kmalloc (count, GFP_ATOMIC); + buffer = kmalloc(count, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); return -ENOMEM; @@ -1104,17 +1101,17 @@ static int garmin_write_bulk (struct usb_serial_port *port, urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { dev_err(&port->dev, "no more free urbs\n"); - kfree (buffer); + kfree(buffer); return -ENOMEM; } - memcpy (buffer, buf, count); + memcpy(buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); - usb_fill_bulk_urb (urb, serial->dev, - usb_sndbulkpipe (serial->dev, - port->bulk_out_endpointAddress), + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), buffer, count, garmin_write_bulk_callback, dismiss_ack ? NULL : port); @@ -1132,33 +1129,29 @@ static int garmin_write_bulk (struct usb_serial_port *port, status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&port->dev, - "%s - usb_submit_urb(write bulk) " - "failed with status = %d\n", + "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status); count = status; } /* we are done with this urb, so let the host driver * really free it when it is finished with it */ - usb_free_urb (urb); + usb_free_urb(urb); return count; } - - -static int garmin_write (struct usb_serial_port *port, - const unsigned char *buf, int count) +static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { int pktid, pktsiz, len; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; usb_serial_debug_data(debug, &port->dev, __func__, count, buf); /* check for our private packets */ if (count >= GARMIN_PKTHDR_LENGTH) { - len = PRIVPKTSIZ; if (count < len) len = count; @@ -1169,15 +1162,16 @@ static int garmin_write (struct usb_serial_port *port, pktid = getPacketId(garmin_data_p->privpkt); if (count == (GARMIN_PKTHDR_LENGTH+pktsiz) - && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) { + && GARMIN_LAYERID_PRIVATE == + getLayerId(garmin_data_p->privpkt)) { dbg("%s - processing private request %d", __func__, pktid); - // drop all unfinished transfers + /* drop all unfinished transfers */ garmin_clear(garmin_data_p); - switch(pktid) { + switch (pktid) { case PRIV_PKTID_SET_DEBUG: if (pktsiz != 4) @@ -1226,44 +1220,31 @@ static int garmin_write (struct usb_serial_port *port, } -static int garmin_write_room (struct usb_serial_port *port) +static int garmin_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; /* * Report back the bytes currently available in the output buffer. */ - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); return GPS_OUT_BUFSIZ-garmin_data_p->outsize; } -static int garmin_chars_in_buffer (struct usb_serial_port *port) -{ - /* - * Report back the number of bytes currently in our input buffer. - * Will this lock up the driver - the buffer contains an incomplete - * package which will not be written to the device until it - * has been completed ? - */ - //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); - //return garmin_data_p->insize; - return 0; -} - - -static void garmin_read_process(struct garmin_data * garmin_data_p, +static void garmin_read_process(struct garmin_data *garmin_data_p, unsigned char *data, unsigned data_length) { if (garmin_data_p->flags & FLAGS_DROP_DATA) { /* abort-transfer cmd is actice */ dbg("%s - pkt dropped", __func__); } else if (garmin_data_p->state != STATE_DISCONNECTED && - garmin_data_p->state != STATE_RESET ) { + garmin_data_p->state != STATE_RESET) { /* remember any appl.layer packets, so we know if a reset is required or not when closing the device */ if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, - sizeof(GARMIN_APP_LAYER_REPLY))) { + sizeof(GARMIN_APP_LAYER_REPLY))) { atomic_inc(&garmin_data_p->resp_count); } @@ -1273,9 +1254,8 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, if (garmin_data_p->flags & FLAGS_QUEUING) { pkt_add(garmin_data_p, data, data_length); } else if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { - if (getLayerId(data) == GARMIN_LAYERID_APPL) { + if (getLayerId(data) == GARMIN_LAYERID_APPL) pkt_add(garmin_data_p, data, data_length); - } } else { send_to_tty(garmin_data_p->port, data, data_length); } @@ -1283,12 +1263,12 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, } -static void garmin_read_bulk_callback (struct urb *urb) +static void garmin_read_bulk_callback(struct urb *urb) { unsigned long flags; struct usb_serial_port *port = urb->context; struct usb_serial *serial = port->serial; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; int status = urb->status; int retval; @@ -1306,7 +1286,7 @@ static void garmin_read_bulk_callback (struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, + usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); garmin_read_process(garmin_data_p, data, urb->actual_length); @@ -1340,13 +1320,13 @@ static void garmin_read_bulk_callback (struct urb *urb) } -static void garmin_read_int_callback (struct urb *urb) +static void garmin_read_int_callback(struct urb *urb) { unsigned long flags; int retval; struct usb_serial_port *port = urb->context; struct usb_serial *serial = port->serial; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; int status = urb->status; @@ -1372,30 +1352,31 @@ static void garmin_read_int_callback (struct urb *urb) if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) && 0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY, - sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) { + sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) { dbg("%s - bulk data available.", __func__); if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { /* bulk data available */ - usb_fill_bulk_urb (port->read_urb, serial->dev, - usb_rcvbulkpipe (serial->dev, - port->bulk_in_endpointAddress), + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, garmin_read_bulk_callback, port); retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (retval) { dev_err(&port->dev, - "%s - failed submitting read urb, error %d\n", - __func__, retval); + "%s - failed submitting read urb, error %d\n", + __func__, retval); } else { spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE; /* do not send this packet to the user */ garmin_data_p->ignorePkts = 1; - spin_unlock_irqrestore(&garmin_data_p->lock, flags); + spin_unlock_irqrestore(&garmin_data_p->lock, + flags); } } else { /* bulk-in transfer still active */ @@ -1406,15 +1387,15 @@ static void garmin_read_int_callback (struct urb *urb) } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY)) && 0 == memcmp(data, GARMIN_START_SESSION_REPLY, - sizeof(GARMIN_START_SESSION_REPLY))) { + sizeof(GARMIN_START_SESSION_REPLY))) { spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN; spin_unlock_irqrestore(&garmin_data_p->lock, flags); /* save the serial number */ - garmin_data_p->serial_num - = __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH)); + garmin_data_p->serial_num = __le32_to_cpup( + (__le32 *)(data+GARMIN_PKTHDR_LENGTH)); dbg("%s - start-of-session reply seen - serial %u.", __func__, garmin_data_p->serial_num); @@ -1433,7 +1414,7 @@ static void garmin_read_int_callback (struct urb *urb) } port->interrupt_in_urb->dev = port->serial->dev; - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", @@ -1446,7 +1427,7 @@ static void garmin_read_int_callback (struct urb *urb) * and then sets a timer to call itself again until all queued data * is sent. */ -static int garmin_flush_queue(struct garmin_data * garmin_data_p) +static int garmin_flush_queue(struct garmin_data *garmin_data_p) { unsigned long flags; struct garmin_packet *pkt; @@ -1468,10 +1449,11 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p) } -static void garmin_throttle (struct usb_serial_port *port) +static void garmin_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); unsigned long flags; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); dbg("%s - port %d", __func__, port->number); /* set flag, data received will be put into a queue @@ -1482,10 +1464,11 @@ static void garmin_throttle (struct usb_serial_port *port) } -static void garmin_unthrottle (struct usb_serial_port *port) +static void garmin_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); unsigned long flags; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); int status; dbg("%s - port %d", __func__, port->number); @@ -1507,8 +1490,6 @@ static void garmin_unthrottle (struct usb_serial_port *port) } } - - /* * The timer is currently only used to send queued packets to * the tty in cases where the protocol provides no own handshaking @@ -1526,11 +1507,11 @@ static void timeout_handler(unsigned long data) -static int garmin_attach (struct usb_serial *serial) +static int garmin_attach(struct usb_serial *serial) { int status = 0; struct usb_serial_port *port = serial->port[0]; - struct garmin_data * garmin_data_p = NULL; + struct garmin_data *garmin_data_p = NULL; dbg("%s", __func__); @@ -1542,7 +1523,7 @@ static int garmin_attach (struct usb_serial *serial) init_timer(&garmin_data_p->timer); spin_lock_init(&garmin_data_p->lock); INIT_LIST_HEAD(&garmin_data_p->pktlist); - //garmin_data_p->timer.expires = jiffies + session_timeout; + /* garmin_data_p->timer.expires = jiffies + session_timeout; */ garmin_data_p->timer.data = (unsigned long)garmin_data_p; garmin_data_p->timer.function = timeout_handler; garmin_data_p->port = port; @@ -1556,16 +1537,16 @@ static int garmin_attach (struct usb_serial *serial) } -static void garmin_shutdown (struct usb_serial *serial) +static void garmin_shutdown(struct usb_serial *serial) { struct usb_serial_port *port = serial->port[0]; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); dbg("%s", __func__); - usb_kill_urb (port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); - kfree (garmin_data_p); + kfree(garmin_data_p); usb_set_serial_port_data(port, NULL); } @@ -1588,7 +1569,6 @@ static struct usb_serial_driver garmin_device = { .shutdown = garmin_shutdown, .write = garmin_write, .write_room = garmin_write_room, - .chars_in_buffer = garmin_chars_in_buffer, .write_bulk_callback = garmin_write_bulk_callback, .read_bulk_callback = garmin_read_bulk_callback, .read_int_callback = garmin_read_int_callback, @@ -1596,7 +1576,7 @@ static struct usb_serial_driver garmin_device = { -static int __init garmin_init (void) +static int __init garmin_init(void) { int retval; @@ -1616,10 +1596,10 @@ failed_garmin_register: } -static void __exit garmin_exit (void) +static void __exit garmin_exit(void) { - usb_deregister (&garmin_driver); - usb_serial_deregister (&garmin_device); + usb_deregister(&garmin_driver); + usb_serial_deregister(&garmin_device); } @@ -1628,8 +1608,8 @@ static void __exit garmin_exit (void) module_init(garmin_init); module_exit(garmin_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IWUSR | S_IRUGO); diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 537f12a027c2..fe84c88ec20c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -18,7 +18,7 @@ #include <linux/moduleparam.h> #include <linux/usb.h> #include <linux/usb/serial.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> static int debug; @@ -81,7 +81,7 @@ static int generic_probe(struct usb_interface *interface, } #endif -int usb_serial_generic_register (int _debug) +int usb_serial_generic_register(int _debug) { int retval = 0; @@ -89,10 +89,11 @@ int usb_serial_generic_register (int _debug) #ifdef CONFIG_USB_SERIAL_GENERIC generic_device_ids[0].idVendor = vendor; generic_device_ids[0].idProduct = product; - generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; + generic_device_ids[0].match_flags = + USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; /* register our generic driver with ourselves */ - retval = usb_serial_register (&usb_serial_generic_device); + retval = usb_serial_register(&usb_serial_generic_device); if (retval) goto exit; retval = usb_register(&generic_driver); @@ -103,16 +104,17 @@ exit: return retval; } -void usb_serial_generic_deregister (void) +void usb_serial_generic_deregister(void) { #ifdef CONFIG_USB_SERIAL_GENERIC /* remove our generic driver */ usb_deregister(&generic_driver); - usb_serial_deregister (&usb_serial_generic_device); + usb_serial_deregister(&usb_serial_generic_device); #endif } -int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) +int usb_serial_generic_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; int result = 0; @@ -120,11 +122,11 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) dbg("%s - port %d", __func__, port->number); - /* force low_latency on so that our tty_push actually forces the data through, - otherwise it is scheduled, and with high data rates (like with OHCI) data - can get lost. */ - if (port->tty) - port->tty->low_latency = 1; + /* force low_latency on so that our tty_push actually forces the data + through, otherwise it is scheduled, and with high data rates (like + with OHCI) data can get lost. */ + if (tty) + tty->low_latency = 1; /* clear the throttle flags */ spin_lock_irqsave(&port->lock, flags); @@ -135,8 +137,9 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) /* if we have a bulk endpoint, start reading from it */ if (serial->num_bulk_in) { /* Start reading from the device */ - usb_fill_bulk_urb (port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, ((serial->type->read_bulk_callback) ? @@ -145,14 +148,16 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); } return result; } EXPORT_SYMBOL_GPL(usb_serial_generic_open); -static void generic_cleanup (struct usb_serial_port *port) +static void generic_cleanup(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; @@ -182,7 +187,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) #endif for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - if (port->open_count && port->read_urb) { + if (port->port.count && port->read_urb) { r = usb_submit_urb(port->read_urb, GFP_NOIO); if (r < 0) c++; @@ -192,13 +197,15 @@ int usb_serial_generic_resume(struct usb_serial *serial) return c ? -EIO : 0; } -void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) +void usb_serial_generic_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __func__, port->number); - generic_cleanup (port); + generic_cleanup(port); } -int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count) +int usb_serial_generic_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; int result; @@ -208,7 +215,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * if (count == 0) { dbg("%s - write request of 0 bytes", __func__); - return (0); + return 0; } /* only do something if we have a bulk out endpoint */ @@ -223,27 +230,32 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * port->write_urb_busy = 1; spin_unlock_irqrestore(&port->lock, flags); - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + count = (count > port->bulk_out_size) ? + port->bulk_out_size : count; - memcpy (port->write_urb->transfer_buffer, buf, count); + memcpy(port->write_urb->transfer_buffer, buf, count); data = port->write_urb->transfer_buffer; usb_serial_debug_data(debug, &port->dev, __func__, count, data); /* set up our urb */ - usb_fill_bulk_urb (port->write_urb, serial->dev, - usb_sndbulkpipe (serial->dev, - port->bulk_out_endpointAddress), + usb_fill_bulk_urb(port->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, count, - ((serial->type->write_bulk_callback) ? + ((serial->type->write_bulk_callback) ? serial->type->write_bulk_callback : - usb_serial_generic_write_bulk_callback), port); + usb_serial_generic_write_bulk_callback), + port); /* send the data out the bulk port */ port->write_urb_busy = 1; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result); - /* don't have to grab the lock here, as we will retry if != 0 */ + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); + /* don't have to grab the lock here, as we will + retry if != 0 */ port->write_urb_busy = 0; } else result = count; @@ -255,8 +267,9 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * return 0; } -int usb_serial_generic_write_room (struct usb_serial_port *port) +int usb_serial_generic_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; int room = 0; @@ -272,8 +285,9 @@ int usb_serial_generic_write_room (struct usb_serial_port *port) return room; } -int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) +int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; int chars = 0; @@ -286,7 +300,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) } dbg("%s - returns %d", __func__, chars); - return (chars); + return chars; } @@ -297,24 +311,26 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) int result; /* Continue reading from device */ - usb_fill_bulk_urb (urb, serial->dev, - usb_rcvbulkpipe (serial->dev, - port->bulk_in_endpointAddress), + usb_fill_bulk_urb(urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), urb->transfer_buffer, urb->transfer_buffer_length, - ((serial->type->read_bulk_callback) ? - serial->type->read_bulk_callback : + ((serial->type->read_bulk_callback) ? + serial->type->read_bulk_callback : usb_serial_generic_read_bulk_callback), port); result = usb_submit_urb(urb, mem_flags); if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); } /* Push data to tty layer and resubmit the bulk read URB */ -static void flush_and_resubmit_read_urb (struct usb_serial_port *port) +static void flush_and_resubmit_read_urb(struct usb_serial_port *port) { struct urb *urb = port->read_urb; - struct tty_struct *tty = port->tty; + struct tty_struct *tty = port->port.tty; int room; /* Push data to tty */ @@ -329,7 +345,7 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port) resubmit_read_urb(port, GFP_ATOMIC); } -void usb_serial_generic_read_bulk_callback (struct urb *urb) +void usb_serial_generic_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; @@ -344,20 +360,21 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); /* Throttle the device if requested by tty */ spin_lock_irqsave(&port->lock, flags); - if (!(port->throttled = port->throttle_req)) { + port->throttled = port->throttle_req; + if (!port->throttled) { spin_unlock_irqrestore(&port->lock, flags); flush_and_resubmit_read_urb(port); - } else { + } else spin_unlock_irqrestore(&port->lock, flags); - } } EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); -void usb_serial_generic_write_bulk_callback (struct urb *urb) +void usb_serial_generic_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; int status = urb->status; @@ -374,8 +391,9 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb) } EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); -void usb_serial_generic_throttle (struct usb_serial_port *port) +void usb_serial_generic_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; unsigned long flags; dbg("%s - port %d", __func__, port->number); @@ -387,8 +405,9 @@ void usb_serial_generic_throttle (struct usb_serial_port *port) spin_unlock_irqrestore(&port->lock, flags); } -void usb_serial_generic_unthrottle (struct usb_serial_port *port) +void usb_serial_generic_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int was_throttled; unsigned long flags; @@ -406,15 +425,14 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port) } } -void usb_serial_generic_shutdown (struct usb_serial *serial) +void usb_serial_generic_shutdown(struct usb_serial *serial) { int i; dbg("%s", __func__); /* stop reads and writes on all ports */ - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) generic_cleanup(serial->port[i]); - } } diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 75b88b356ebc..ab905869e959 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -9,7 +9,8 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver */ #include <linux/kernel.h> diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 2fd449bcfa35..bfa508ddb0fe 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -44,7 +44,7 @@ #include <linux/wait.h> #include <linux/firmware.h> #include <linux/ihex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "io_edgeport.h" @@ -66,16 +66,16 @@ /* receive port state */ enum RXSTATE { - EXPECT_HDR1 = 0, /* Expect header byte 1 */ - EXPECT_HDR2 = 1, /* Expect header byte 2 */ - EXPECT_DATA = 2, /* Expect 'RxBytesRemaining' data */ - EXPECT_HDR3 = 3, /* Expect header byte 3 (for status hdrs only) */ + EXPECT_HDR1 = 0, /* Expect header byte 1 */ + EXPECT_HDR2 = 1, /* Expect header byte 2 */ + EXPECT_DATA = 2, /* Expect 'RxBytesRemaining' data */ + EXPECT_HDR3 = 3, /* Expect header byte 3 (for status hdrs only) */ }; -/* Transmit Fifo - * This Transmit queue is an extension of the edgeport Rx buffer. - * The maximum amount of data buffered in both the edgeport +/* Transmit Fifo + * This Transmit queue is an extension of the edgeport Rx buffer. + * The maximum amount of data buffered in both the edgeport * Rx buffer (maxTxCredits) and this buffer will never exceed maxTxCredits. */ struct TxFifo { @@ -132,12 +132,12 @@ struct edgeport_serial { int is_epic; /* flag if EPiC device or not */ __u8 interrupt_in_endpoint; /* the interrupt endpoint handle */ - unsigned char * interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ - struct urb * interrupt_read_urb; /* our interrupt urb */ + unsigned char *interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ + struct urb *interrupt_read_urb; /* our interrupt urb */ __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ - unsigned char * bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ - struct urb * read_urb; /* our bulk read urb */ + unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ + struct urb *read_urb; /* our bulk read urb */ bool read_in_progress; spinlock_t es_lock; @@ -162,16 +162,17 @@ struct divisor_table_entry { __u16 Divisor; }; -// -// Define table of divisors for Rev A EdgePort/4 hardware -// These assume a 3.6864MHz crystal, the standard /16, and -// MCR.7 = 0. -// +/* + * Define table of divisors for Rev A EdgePort/4 hardware + * These assume a 3.6864MHz crystal, the standard /16, and + * MCR.7 = 0. + */ + static const struct divisor_table_entry divisor_table[] = { - { 50, 4608}, - { 75, 3072}, - { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */ - { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */ + { 50, 4608}, + { 75, 3072}, + { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */ + { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */ { 150, 1536}, { 300, 768}, { 600, 384}, @@ -194,64 +195,86 @@ static int debug; static int low_latency = 1; /* tty low latency flag, on by default */ -static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */ +static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */ /* local function prototypes */ /* function prototypes for all URB callbacks */ -static void edge_interrupt_callback (struct urb *urb); -static void edge_bulk_in_callback (struct urb *urb); -static void edge_bulk_out_data_callback (struct urb *urb); -static void edge_bulk_out_cmd_callback (struct urb *urb); +static void edge_interrupt_callback(struct urb *urb); +static void edge_bulk_in_callback(struct urb *urb); +static void edge_bulk_out_data_callback(struct urb *urb); +static void edge_bulk_out_cmd_callback(struct urb *urb); /* function prototypes for the usbserial callbacks */ -static int edge_open (struct usb_serial_port *port, struct file *filp); -static void edge_close (struct usb_serial_port *port, struct file *filp); -static int edge_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static int edge_write_room (struct usb_serial_port *port); -static int edge_chars_in_buffer (struct usb_serial_port *port); -static void edge_throttle (struct usb_serial_port *port); -static void edge_unthrottle (struct usb_serial_port *port); -static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); -static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); -static void edge_break (struct usb_serial_port *port, int break_state); -static int edge_tiocmget (struct usb_serial_port *port, struct file *file); -static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); -static int edge_startup (struct usb_serial *serial); -static void edge_shutdown (struct usb_serial *serial); - +static int edge_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static void edge_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static int edge_write_room(struct tty_struct *tty); +static int edge_chars_in_buffer(struct tty_struct *tty); +static void edge_throttle(struct tty_struct *tty); +static void edge_unthrottle(struct tty_struct *tty); +static void edge_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, + struct ktermios *old_termios); +static int edge_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void edge_break(struct tty_struct *tty, int break_state); +static int edge_tiocmget(struct tty_struct *tty, struct file *file); +static int edge_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static int edge_startup(struct usb_serial *serial); +static void edge_shutdown(struct usb_serial *serial); #include "io_tables.h" /* all of the devices that this driver supports */ /* function prototypes for all of our local functions */ -static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength); -static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3); -static void edge_tty_recv (struct device *dev, struct tty_struct *tty, unsigned char *data, int length); -static void handle_new_msr (struct edgeport_port *edge_port, __u8 newMsr); -static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data); -static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param); -static int calc_baud_rate_divisor (int baud_rate, int *divisor); -static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate); -static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios); -static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue); -static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength); -static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port); - -static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data); -static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data); -static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data); -static void get_manufacturing_desc (struct edgeport_serial *edge_serial); -static void get_boot_desc (struct edgeport_serial *edge_serial); -static void load_application_firmware (struct edgeport_serial *edge_serial); - -static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size); - - -// ************************************************************************ -// ************************************************************************ -// ************************************************************************ -// ************************************************************************ + +static void process_rcvd_data(struct edgeport_serial *edge_serial, + unsigned char *buffer, __u16 bufferLength); +static void process_rcvd_status(struct edgeport_serial *edge_serial, + __u8 byte2, __u8 byte3); +static void edge_tty_recv(struct device *dev, struct tty_struct *tty, + unsigned char *data, int length); +static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr); +static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, + __u8 lsr, __u8 data); +static int send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command, + __u8 param); +static int calc_baud_rate_divisor(int baud_rate, int *divisor); +static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, + int baudRate); +static void change_port_settings(struct tty_struct *tty, + struct edgeport_port *edge_port, + struct ktermios *old_termios); +static int send_cmd_write_uart_register(struct edgeport_port *edge_port, + __u8 regNum, __u8 regValue); +static int write_cmd_usb(struct edgeport_port *edge_port, + unsigned char *buffer, int writeLength); +static void send_more_port_data(struct edgeport_serial *edge_serial, + struct edgeport_port *edge_port); + +static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, + __u16 length, const __u8 *data); +static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 addr, + __u16 length, __u8 *data); +static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, + __u16 length, const __u8 *data); +static void get_manufacturing_desc(struct edgeport_serial *edge_serial); +static void get_boot_desc(struct edgeport_serial *edge_serial); +static void load_application_firmware(struct edgeport_serial *edge_serial); + +static void unicode_to_ascii(char *string, int buflen, + __le16 *unicode, int unicode_size); + + +/* ************************************************************************ */ +/* ************************************************************************ */ +/* ************************************************************************ */ +/* ************************************************************************ */ /************************************************************************ * * @@ -261,7 +284,7 @@ static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unic * embedded in this driver * * * ************************************************************************/ -static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) +static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) { __u32 BootCurVer; __u32 BootNewVer; @@ -275,16 +298,14 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) int response; switch (edge_serial->product_info.iDownloadFile) { - case EDGE_DOWNLOAD_FILE_I930: - fw_name = "edgeport/boot.fw"; - break; - - case EDGE_DOWNLOAD_FILE_80251: - fw_name = "edgeport/boot2.fw"; - break; - - default: - return; + case EDGE_DOWNLOAD_FILE_I930: + fw_name = "edgeport/boot.fw"; + break; + case EDGE_DOWNLOAD_FILE_80251: + fw_name = "edgeport/boot2.fw"; + break; + default: + return; } response = request_ihex_firmware(&fw, fw_name, @@ -300,7 +321,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) BootMinorVersion = rec->data[1]; BootBuildNumber = (rec->data[2] << 8) | rec->data[3]; - // Check Boot Image Version + /* Check Boot Image Version */ BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) + (edge_serial->boot_descriptor.MinorVersion << 16) + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber); @@ -352,29 +373,29 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) * Get string descriptor from device * * * ************************************************************************/ -static int get_string (struct usb_device *dev, int Id, char *string, int buflen) +static int get_string(struct usb_device *dev, int Id, char *string, int buflen) { struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; - dbg("%s - USB String ID = %d", __func__, Id ); + dbg("%s - USB String ID = %d", __func__, Id); - if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) { + if (!usb_get_descriptor(dev, USB_DT_STRING, Id, + &StringDesc, sizeof(StringDesc))) return 0; - } - pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL); - - if (!pStringDesc) { + pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL); + if (!pStringDesc) return 0; - } - if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) { + if (!usb_get_descriptor(dev, USB_DT_STRING, Id, + pStringDesc, StringDesc.bLength)) { kfree(pStringDesc); return 0; } - unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2); + unicode_to_ascii(string, buflen, + pStringDesc->wData, pStringDesc->bLength/2); kfree(pStringDesc); dbg("%s - USB String %s", __func__, string); @@ -388,24 +409,24 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen) * Get string descriptor from device * ************************************************************************/ -static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc) +static int get_string_desc(struct usb_device *dev, int Id, + struct usb_string_descriptor **pRetDesc) { struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; - dbg("%s - USB String ID = %d", __func__, Id ); + dbg("%s - USB String ID = %d", __func__, Id); - if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) { + if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, + sizeof(StringDesc))) return 0; - } - pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL); - - if (!pStringDesc) { + pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL); + if (!pStringDesc) return -1; - } - if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) { + if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, + StringDesc.bLength)) { kfree(pStringDesc); return -1; } @@ -417,25 +438,30 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de static void dump_product_info(struct edgeport_product_info *product_info) { - // Dump Product Info structure + /* Dump Product Info structure */ dbg("**Product Information:"); - dbg(" ProductId %x", product_info->ProductId ); - dbg(" NumPorts %d", product_info->NumPorts ); - dbg(" ProdInfoVer %d", product_info->ProdInfoVer ); + dbg(" ProductId %x", product_info->ProductId); + dbg(" NumPorts %d", product_info->NumPorts); + dbg(" ProdInfoVer %d", product_info->ProdInfoVer); dbg(" IsServer %d", product_info->IsServer); - dbg(" IsRS232 %d", product_info->IsRS232 ); - dbg(" IsRS422 %d", product_info->IsRS422 ); - dbg(" IsRS485 %d", product_info->IsRS485 ); - dbg(" RomSize %d", product_info->RomSize ); - dbg(" RamSize %d", product_info->RamSize ); - dbg(" CpuRev %x", product_info->CpuRev ); + dbg(" IsRS232 %d", product_info->IsRS232); + dbg(" IsRS422 %d", product_info->IsRS422); + dbg(" IsRS485 %d", product_info->IsRS485); + dbg(" RomSize %d", product_info->RomSize); + dbg(" RamSize %d", product_info->RamSize); + dbg(" CpuRev %x", product_info->CpuRev); dbg(" BoardRev %x", product_info->BoardRev); dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, product_info->BootMinorVersion, le16_to_cpu(product_info->BootBuildNumber)); - dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], - product_info->ManufactureDescDate[1], - product_info->ManufactureDescDate[2]+1900); + dbg(" FirmwareMajorVersion %d.%d.%d", + product_info->FirmwareMajorVersion, + product_info->FirmwareMinorVersion, + le16_to_cpu(product_info->FirmwareBuildNumber)); + dbg(" ManufactureDescDate %d/%d/%d", + product_info->ManufactureDescDate[0], + product_info->ManufactureDescDate[1], + product_info->ManufactureDescDate[2]+1900); dbg(" iDownloadFile 0x%x", product_info->iDownloadFile); dbg(" EpicVer %d", product_info->EpicVer); } @@ -444,55 +470,60 @@ static void get_product_info(struct edgeport_serial *edge_serial) { struct edgeport_product_info *product_info = &edge_serial->product_info; - memset (product_info, 0, sizeof(struct edgeport_product_info)); - - product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP); - product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts; - product_info->ProdInfoVer = 0; - - product_info->RomSize = edge_serial->manuf_descriptor.RomSize; - product_info->RamSize = edge_serial->manuf_descriptor.RamSize; - product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev; - product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev; - - product_info->BootMajorVersion = edge_serial->boot_descriptor.MajorVersion; - product_info->BootMinorVersion = edge_serial->boot_descriptor.MinorVersion; - product_info->BootBuildNumber = edge_serial->boot_descriptor.BuildNumber; - - memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate)); - - // check if this is 2nd generation hardware - if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ION_DEVICE_ID_80251_NETCHIP) { - product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; - } else { - product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; - } - - // Determine Product type and set appropriate flags + memset(product_info, 0, sizeof(struct edgeport_product_info)); + + product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP); + product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts; + product_info->ProdInfoVer = 0; + + product_info->RomSize = edge_serial->manuf_descriptor.RomSize; + product_info->RamSize = edge_serial->manuf_descriptor.RamSize; + product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev; + product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev; + + product_info->BootMajorVersion = + edge_serial->boot_descriptor.MajorVersion; + product_info->BootMinorVersion = + edge_serial->boot_descriptor.MinorVersion; + product_info->BootBuildNumber = + edge_serial->boot_descriptor.BuildNumber; + + memcpy(product_info->ManufactureDescDate, + edge_serial->manuf_descriptor.DescDate, + sizeof(edge_serial->manuf_descriptor.DescDate)); + + /* check if this is 2nd generation hardware */ + if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) + & ION_DEVICE_ID_80251_NETCHIP) + product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; + else + product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; + + /* Determine Product type and set appropriate flags */ switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) { - case ION_DEVICE_ID_EDGEPORT_COMPATIBLE: - case ION_DEVICE_ID_EDGEPORT_4T: - case ION_DEVICE_ID_EDGEPORT_4: - case ION_DEVICE_ID_EDGEPORT_2: - case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU: - case ION_DEVICE_ID_EDGEPORT_8: - case ION_DEVICE_ID_EDGEPORT_421: - case ION_DEVICE_ID_EDGEPORT_21: - case ION_DEVICE_ID_EDGEPORT_2_DIN: - case ION_DEVICE_ID_EDGEPORT_4_DIN: - case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU: - product_info->IsRS232 = 1; - break; + case ION_DEVICE_ID_EDGEPORT_COMPATIBLE: + case ION_DEVICE_ID_EDGEPORT_4T: + case ION_DEVICE_ID_EDGEPORT_4: + case ION_DEVICE_ID_EDGEPORT_2: + case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU: + case ION_DEVICE_ID_EDGEPORT_8: + case ION_DEVICE_ID_EDGEPORT_421: + case ION_DEVICE_ID_EDGEPORT_21: + case ION_DEVICE_ID_EDGEPORT_2_DIN: + case ION_DEVICE_ID_EDGEPORT_4_DIN: + case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU: + product_info->IsRS232 = 1; + break; - case ION_DEVICE_ID_EDGEPORT_2I: // Edgeport/2 RS422/RS485 - product_info->IsRS422 = 1; - product_info->IsRS485 = 1; - break; + case ION_DEVICE_ID_EDGEPORT_2I: /* Edgeport/2 RS422/RS485 */ + product_info->IsRS422 = 1; + product_info->IsRS485 = 1; + break; - case ION_DEVICE_ID_EDGEPORT_8I: // Edgeport/4 RS422 - case ION_DEVICE_ID_EDGEPORT_4I: // Edgeport/4 RS422 - product_info->IsRS422 = 1; - break; + case ION_DEVICE_ID_EDGEPORT_8I: /* Edgeport/4 RS422 */ + case ION_DEVICE_ID_EDGEPORT_4I: /* Edgeport/4 RS422 */ + product_info->IsRS422 = 1; + break; } dump_product_info(product_info); @@ -520,32 +551,32 @@ static int get_epic_descriptor(struct edgeport_serial *ep) ep->is_epic = 1; memset(product_info, 0, sizeof(struct edgeport_product_info)); - product_info->NumPorts = epic->NumPorts; - product_info->ProdInfoVer = 0; - product_info->FirmwareMajorVersion = epic->MajorVersion; - product_info->FirmwareMinorVersion = epic->MinorVersion; - product_info->FirmwareBuildNumber = epic->BuildNumber; - product_info->iDownloadFile = epic->iDownloadFile; - product_info->EpicVer = epic->EpicVer; - product_info->Epic = epic->Supports; - product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE; + product_info->NumPorts = epic->NumPorts; + product_info->ProdInfoVer = 0; + product_info->FirmwareMajorVersion = epic->MajorVersion; + product_info->FirmwareMinorVersion = epic->MinorVersion; + product_info->FirmwareBuildNumber = epic->BuildNumber; + product_info->iDownloadFile = epic->iDownloadFile; + product_info->EpicVer = epic->EpicVer; + product_info->Epic = epic->Supports; + product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE; dump_product_info(product_info); bits = &ep->epic_descriptor.Supports; dbg("**EPIC descriptor:"); dbg(" VendEnableSuspend: %s", bits->VendEnableSuspend ? "TRUE": "FALSE"); - dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE" ); - dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE" ); - dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE" ); - dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE" ); - dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE" ); - dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE" ); - dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE" ); - dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE" ); - dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE" ); - dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE" ); - dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE" ); - dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE" ); + dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE"); + dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE"); + dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE"); + dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE"); + dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE"); + dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE"); + dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE"); + dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE"); + dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE"); + dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE"); + dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE"); + dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE"); } return result; @@ -561,10 +592,10 @@ static int get_epic_descriptor(struct edgeport_serial *ep) /***************************************************************************** * edge_interrupt_callback - * this is the callback function for when we have received data on the + * this is the callback function for when we have received data on the * interrupt endpoint. *****************************************************************************/ -static void edge_interrupt_callback (struct urb *urb) +static void edge_interrupt_callback(struct urb *urb) { struct edgeport_serial *edge_serial = urb->context; struct edgeport_port *edge_port; @@ -589,17 +620,17 @@ static void edge_interrupt_callback (struct urb *urb) case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", - __func__, status); + __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", - __func__, status); + dbg("%s - nonzero urb status received: %d", __func__, status); goto exit; } - // process this interrupt-read even if there are no ports open + /* process this interrupt-read even if there are no ports open */ if (length) { - usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data); + usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, + __func__, length, data); if (length > 1) { bytes_avail = data[0] | (data[1] << 8); @@ -613,7 +644,8 @@ static void edge_interrupt_callback (struct urb *urb) dbg("%s - posting a read", __func__); edge_serial->read_in_progress = true; - /* we have pending bytes on the bulk in pipe, send a request */ + /* we have pending bytes on the + bulk in pipe, send a request */ edge_serial->read_urb->dev = edge_serial->serial->dev; result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); if (result) { @@ -627,7 +659,8 @@ static void edge_interrupt_callback (struct urb *urb) /* grab the txcredits for the ports if available */ position = 2; portNumber = 0; - while ((position < length) && (portNumber < edge_serial->serial->num_ports)) { + while ((position < length) && + (portNumber < edge_serial->serial->num_ports)) { txCredits = data[position] | (data[position+1] << 8); if (txCredits) { port = edge_serial->serial->port[portNumber]; @@ -636,14 +669,19 @@ static void edge_interrupt_callback (struct urb *urb) spin_lock(&edge_port->ep_lock); edge_port->txCredits += txCredits; spin_unlock(&edge_port->ep_lock); - dbg("%s - txcredits for port%d = %d", __func__, portNumber, edge_port->txCredits); - - /* tell the tty driver that something has changed */ - if (edge_port->port->tty) - tty_wakeup(edge_port->port->tty); - - // Since we have more credit, check if more data can be sent - send_more_port_data(edge_serial, edge_port); + dbg("%s - txcredits for port%d = %d", + __func__, portNumber, + edge_port->txCredits); + + /* tell the tty driver that something + has changed */ + if (edge_port->port->port.tty) + tty_wakeup(edge_port->port->port.tty); + + /* Since we have more credit, check + if more data can be sent */ + send_more_port_data(edge_serial, + edge_port); } } position += 2; @@ -652,19 +690,20 @@ static void edge_interrupt_callback (struct urb *urb) } exit: - result = usb_submit_urb (urb, GFP_ATOMIC); - if (result) { - dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result); - } + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + dev_err(&urb->dev->dev, + "%s - Error %d submitting control urb\n", + __func__, result); } /***************************************************************************** * edge_bulk_in_callback - * this is the callback function for when we have received data on the + * this is the callback function for when we have received data on the * bulk in endpoint. *****************************************************************************/ -static void edge_bulk_in_callback (struct urb *urb) +static void edge_bulk_in_callback(struct urb *urb) { struct edgeport_serial *edge_serial = urb->context; unsigned char *data = urb->transfer_buffer; @@ -689,16 +728,18 @@ static void edge_bulk_in_callback (struct urb *urb) raw_data_length = urb->actual_length; - usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, raw_data_length, data); + usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, + __func__, raw_data_length, data); spin_lock(&edge_serial->es_lock); /* decrement our rxBytes available by the number that we just got */ edge_serial->rxBytesAvail -= raw_data_length; - dbg("%s - Received = %d, rxBytesAvail %d", __func__, raw_data_length, edge_serial->rxBytesAvail); + dbg("%s - Received = %d, rxBytesAvail %d", __func__, + raw_data_length, edge_serial->rxBytesAvail); - process_rcvd_data (edge_serial, data, urb->actual_length); + process_rcvd_data(edge_serial, data, urb->actual_length); /* check to see if there's any more data for us to read */ if (edge_serial->rxBytesAvail > 0) { @@ -721,10 +762,10 @@ static void edge_bulk_in_callback (struct urb *urb) /***************************************************************************** * edge_bulk_out_data_callback - * this is the callback function for when we have finished sending serial data - * on the bulk out endpoint. + * this is the callback function for when we have finished sending + * serial data on the bulk out endpoint. *****************************************************************************/ -static void edge_bulk_out_data_callback (struct urb *urb) +static void edge_bulk_out_data_callback(struct urb *urb) { struct edgeport_port *edge_port = urb->context; struct tty_struct *tty; @@ -737,27 +778,29 @@ static void edge_bulk_out_data_callback (struct urb *urb) __func__, status); } - tty = edge_port->port->tty; + tty = edge_port->port->port.tty; if (tty && edge_port->open) { - /* let the tty driver wakeup if it has a special write_wakeup function */ + /* let the tty driver wakeup if it has a special + write_wakeup function */ tty_wakeup(tty); } - // Release the Write URB + /* Release the Write URB */ edge_port->write_in_progress = false; - // Check if more data needs to be sent - send_more_port_data((struct edgeport_serial *)(usb_get_serial_data(edge_port->port->serial)), edge_port); + /* Check if more data needs to be sent */ + send_more_port_data((struct edgeport_serial *) + (usb_get_serial_data(edge_port->port->serial)), edge_port); } /***************************************************************************** * BulkOutCmdCallback - * this is the callback function for when we have finished sending a command - * on the bulk out endpoint. + * this is the callback function for when we have finished sending a + * command on the bulk out endpoint. *****************************************************************************/ -static void edge_bulk_out_cmd_callback (struct urb *urb) +static void edge_bulk_out_cmd_callback(struct urb *urb) { struct edgeport_port *edge_port = urb->context; struct tty_struct *tty; @@ -766,22 +809,24 @@ static void edge_bulk_out_cmd_callback (struct urb *urb) dbg("%s", __func__); atomic_dec(&CmdUrbs); - dbg("%s - FREE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs)); + dbg("%s - FREE URB %p (outstanding %d)", __func__, + urb, atomic_read(&CmdUrbs)); /* clean up the transfer buffer */ kfree(urb->transfer_buffer); /* Free the command urb */ - usb_free_urb (urb); + usb_free_urb(urb); if (status) { - dbg("%s - nonzero write bulk status received: %d", __func__, status); + dbg("%s - nonzero write bulk status received: %d", + __func__, status); return; } /* Get pointer to tty */ - tty = edge_port->port->tty; + tty = edge_port->port->port.tty; /* tell the tty driver that something has changed */ if (tty && edge_port->open) @@ -803,7 +848,8 @@ static void edge_bulk_out_cmd_callback (struct urb *urb) * If successful, we return 0 * Otherwise we return a negative error number. *****************************************************************************/ -static int edge_open (struct usb_serial_port *port, struct file * filp) +static int edge_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct usb_serial *serial; @@ -815,55 +861,62 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) if (edge_port == NULL) return -ENODEV; - if (port->tty) - port->tty->low_latency = low_latency; + if (tty) + tty->low_latency = low_latency; - /* see if we've set up our endpoint info yet (can't set it up in edge_startup - as the structures were not set up at that time.) */ + /* see if we've set up our endpoint info yet (can't set it up + in edge_startup as the structures were not set up at that time.) */ serial = port->serial; edge_serial = usb_get_serial_data(serial); - if (edge_serial == NULL) { + if (edge_serial == NULL) return -ENODEV; - } if (edge_serial->interrupt_in_buffer == NULL) { struct usb_serial_port *port0 = serial->port[0]; - + /* not set up yet, so do it now */ - edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer; - edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress; + edge_serial->interrupt_in_buffer = + port0->interrupt_in_buffer; + edge_serial->interrupt_in_endpoint = + port0->interrupt_in_endpointAddress; edge_serial->interrupt_read_urb = port0->interrupt_in_urb; edge_serial->bulk_in_buffer = port0->bulk_in_buffer; - edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress; + edge_serial->bulk_in_endpoint = + port0->bulk_in_endpointAddress; edge_serial->read_urb = port0->read_urb; - edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress; - + edge_serial->bulk_out_endpoint = + port0->bulk_out_endpointAddress; + /* set up our interrupt urb */ usb_fill_int_urb(edge_serial->interrupt_read_urb, - serial->dev, - usb_rcvintpipe(serial->dev, - port0->interrupt_in_endpointAddress), - port0->interrupt_in_buffer, - edge_serial->interrupt_read_urb->transfer_buffer_length, - edge_interrupt_callback, edge_serial, - edge_serial->interrupt_read_urb->interval); - + serial->dev, + usb_rcvintpipe(serial->dev, + port0->interrupt_in_endpointAddress), + port0->interrupt_in_buffer, + edge_serial->interrupt_read_urb->transfer_buffer_length, + edge_interrupt_callback, edge_serial, + edge_serial->interrupt_read_urb->interval); + /* set up our bulk in urb */ usb_fill_bulk_urb(edge_serial->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - port0->bulk_in_endpointAddress), - port0->bulk_in_buffer, - edge_serial->read_urb->transfer_buffer_length, - edge_bulk_in_callback, edge_serial); + usb_rcvbulkpipe(serial->dev, + port0->bulk_in_endpointAddress), + port0->bulk_in_buffer, + edge_serial->read_urb->transfer_buffer_length, + edge_bulk_in_callback, edge_serial); edge_serial->read_in_progress = false; /* start interrupt read for this edgeport - * this interrupt will continue as long as the edgeport is connected */ - response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL); + * this interrupt will continue as long + * as the edgeport is connected */ + response = usb_submit_urb(edge_serial->interrupt_read_urb, + GFP_KERNEL); if (response) { - dev_err(&port->dev, "%s - Error %d submitting control urb\n", __func__, response); + dev_err(&port->dev, + "%s - Error %d submitting control urb\n", + __func__, response); } } - + /* initialize our wait queues */ init_waitqueue_head(&edge_port->wait_open); init_waitqueue_head(&edge_port->wait_chase); @@ -871,26 +924,29 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) init_waitqueue_head(&edge_port->wait_command); /* initialize our icount structure */ - memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount)); + memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); /* initialize our port settings */ - edge_port->txCredits = 0; /* Can't send any data yet */ - edge_port->shadowMCR = MCR_MASTER_IE; /* Must always set this bit to enable ints! */ + edge_port->txCredits = 0; /* Can't send any data yet */ + /* Must always set this bit to enable ints! */ + edge_port->shadowMCR = MCR_MASTER_IE; edge_port->chaseResponsePending = false; /* send a open port command */ edge_port->openPending = true; edge_port->open = false; - response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0); + response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0); if (response < 0) { - dev_err(&port->dev, "%s - error sending open port command\n", __func__); + dev_err(&port->dev, "%s - error sending open port command\n", + __func__); edge_port->openPending = false; return -ENODEV; } /* now wait for the port to be completely opened */ - wait_event_timeout(edge_port->wait_open, !edge_port->openPending, OPEN_TIMEOUT); + wait_event_timeout(edge_port->wait_open, !edge_port->openPending, + OPEN_TIMEOUT); if (!edge_port->open) { /* open timed out */ @@ -904,25 +960,26 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) edge_port->txfifo.tail = 0; edge_port->txfifo.count = 0; edge_port->txfifo.size = edge_port->maxTxCredits; - edge_port->txfifo.fifo = kmalloc (edge_port->maxTxCredits, GFP_KERNEL); + edge_port->txfifo.fifo = kmalloc(edge_port->maxTxCredits, GFP_KERNEL); if (!edge_port->txfifo.fifo) { dbg("%s - no memory", __func__); - edge_close (port, filp); + edge_close(tty, port, filp); return -ENOMEM; } /* Allocate a URB for the write */ - edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL); + edge_port->write_urb = usb_alloc_urb(0, GFP_KERNEL); edge_port->write_in_progress = false; if (!edge_port->write_urb) { dbg("%s - no memory", __func__); - edge_close (port, filp); + edge_close(tty, port, filp); return -ENOMEM; } - dbg("%s(%d) - Initialize TX fifo to %d bytes", __func__, port->number, edge_port->maxTxCredits); + dbg("%s(%d) - Initialize TX fifo to %d bytes", + __func__, port->number, edge_port->maxTxCredits); dbg("%s exited", __func__); @@ -948,27 +1005,28 @@ static void block_until_chase_response(struct edgeport_port *edge_port) int loop = 10; while (1) { - // Save Last credits + /* Save Last credits */ lastCredits = edge_port->txCredits; - // Did we get our Chase response + /* Did we get our Chase response */ if (!edge_port->chaseResponsePending) { dbg("%s - Got Chase Response", __func__); - // did we get all of our credit back? - if (edge_port->txCredits == edge_port->maxTxCredits ) { + /* did we get all of our credit back? */ + if (edge_port->txCredits == edge_port->maxTxCredits) { dbg("%s - Got all credits", __func__); return; } } - // Block the thread for a while - prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE); + /* Block the thread for a while */ + prepare_to_wait(&edge_port->wait_chase, &wait, + TASK_UNINTERRUPTIBLE); schedule_timeout(timeout); finish_wait(&edge_port->wait_chase, &wait); if (lastCredits == edge_port->txCredits) { - // No activity.. count down. + /* No activity.. count down. */ loop--; if (loop == 0) { edge_port->chaseResponsePending = false; @@ -976,8 +1034,9 @@ static void block_until_chase_response(struct edgeport_port *edge_port) return; } } else { - // Reset timeout value back to 10 seconds - dbg("%s - Last %d, Current %d", __func__, lastCredits, edge_port->txCredits); + /* Reset timeout value back to 10 seconds */ + dbg("%s - Last %d, Current %d", __func__, + lastCredits, edge_port->txCredits); loop = 10; } } @@ -994,7 +1053,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port) * 3. A timeout of 3 seconds without activity has expired * ************************************************************************/ -static void block_until_tx_empty (struct edgeport_port *edge_port) +static void block_until_tx_empty(struct edgeport_port *edge_port) { DEFINE_WAIT(wait); struct TxFifo *fifo = &edge_port->txfifo; @@ -1003,31 +1062,32 @@ static void block_until_tx_empty (struct edgeport_port *edge_port) int loop = 30; while (1) { - // Save Last count + /* Save Last count */ lastCount = fifo->count; - // Is the Edgeport Buffer empty? + /* Is the Edgeport Buffer empty? */ if (lastCount == 0) { dbg("%s - TX Buffer Empty", __func__); return; } - // Block the thread for a while - prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE); + /* Block the thread for a while */ + prepare_to_wait(&edge_port->wait_chase, &wait, + TASK_UNINTERRUPTIBLE); schedule_timeout(timeout); finish_wait(&edge_port->wait_chase, &wait); dbg("%s wait", __func__); if (lastCount == fifo->count) { - // No activity.. count down. + /* No activity.. count down. */ loop--; if (loop == 0) { dbg("%s - TIMEOUT", __func__); return; } } else { - // Reset timeout value back to seconds + /* Reset timeout value back to seconds */ loop = 30; } } @@ -1038,20 +1098,21 @@ static void block_until_tx_empty (struct edgeport_port *edge_port) * edge_close * this function is called by the tty driver when a port is closed *****************************************************************************/ -static void edge_close (struct usb_serial_port *port, struct file * filp) +static void edge_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; int status; dbg("%s - port %d", __func__, port->number); - + edge_serial = usb_get_serial_data(port->serial); edge_port = usb_get_serial_port_data(port); - if ((edge_serial == NULL) || (edge_port == NULL)) + if (edge_serial == NULL || edge_port == NULL) return; - - // block until tx is empty + + /* block until tx is empty */ block_until_tx_empty(edge_port); edge_port->closePending = true; @@ -1063,13 +1124,12 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) edge_port->chaseResponsePending = true; dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); - if (status == 0) { - // block until chase finished + status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0); + if (status == 0) + /* block until chase finished */ block_until_chase_response(edge_port); - } else { + else edge_port->chaseResponsePending = false; - } } if ((!edge_serial->is_epic) || @@ -1077,10 +1137,10 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) (edge_serial->epic_descriptor.Supports.IOSPClose))) { /* close the port */ dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__); - send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0); + send_iosp_ext_cmd(edge_port, IOSP_CMD_CLOSE_PORT, 0); } - //port->close = true; + /* port->close = true; */ edge_port->closePending = false; edge_port->open = false; edge_port->openPending = false; @@ -1088,7 +1148,8 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) usb_kill_urb(edge_port->write_urb); if (edge_port->write_urb) { - /* if this urb had a transfer buffer already (old transfer) free it */ + /* if this urb had a transfer buffer already + (old transfer) free it */ kfree(edge_port->write_urb->transfer_buffer); usb_free_urb(edge_port->write_urb); edge_port->write_urb = NULL; @@ -1097,16 +1158,17 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) edge_port->txfifo.fifo = NULL; dbg("%s exited", __func__); -} +} /***************************************************************************** * SerialWrite - * this function is called by the tty driver when data should be written to - * the port. - * If successful, we return the number of bytes written, otherwise we return - * a negative error number. + * this function is called by the tty driver when data should be written + * to the port. + * If successful, we return the number of bytes written, otherwise we + * return a negative error number. *****************************************************************************/ -static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) +static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *data, int count) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct TxFifo *fifo; @@ -1121,66 +1183,76 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data, if (edge_port == NULL) return -ENODEV; - // get a pointer to the Tx fifo + /* get a pointer to the Tx fifo */ fifo = &edge_port->txfifo; spin_lock_irqsave(&edge_port->ep_lock, flags); - // calculate number of bytes to put in fifo - copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count)); + /* calculate number of bytes to put in fifo */ + copySize = min((unsigned int)count, + (edge_port->txCredits - fifo->count)); - dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", __func__, - port->number, count, edge_port->txCredits - fifo->count, copySize); + dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", + __func__, port->number, count, + edge_port->txCredits - fifo->count, copySize); - /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */ + /* catch writes of 0 bytes which the tty driver likes to give us, + and when txCredits is empty */ if (copySize == 0) { dbg("%s - copySize = Zero", __func__); goto finish_write; } - // queue the data - // since we can never overflow the buffer we do not have to check for full condition - - // the copy is done is two parts -- first fill to the end of the buffer - // then copy the reset from the start of the buffer - + /* queue the data + * since we can never overflow the buffer we do not have to check for a + * full condition + * + * the copy is done is two parts -- first fill to the end of the buffer + * then copy the reset from the start of the buffer + */ bytesleft = fifo->size - fifo->head; - firsthalf = min (bytesleft, copySize); - dbg("%s - copy %d bytes of %d into fifo ", __func__, firsthalf, bytesleft); + firsthalf = min(bytesleft, copySize); + dbg("%s - copy %d bytes of %d into fifo ", __func__, + firsthalf, bytesleft); /* now copy our data */ memcpy(&fifo->fifo[fifo->head], data, firsthalf); - usb_serial_debug_data(debug, &port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]); + usb_serial_debug_data(debug, &port->dev, __func__, + firsthalf, &fifo->fifo[fifo->head]); - // update the index and size + /* update the index and size */ fifo->head += firsthalf; fifo->count += firsthalf; - // wrap the index - if (fifo->head == fifo->size) { + /* wrap the index */ + if (fifo->head == fifo->size) fifo->head = 0; - } secondhalf = copySize-firsthalf; if (secondhalf) { dbg("%s - copy rest of data %d", __func__, secondhalf); memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); - usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]); - // update the index and size + usb_serial_debug_data(debug, &port->dev, __func__, + secondhalf, &fifo->fifo[fifo->head]); + /* update the index and size */ fifo->count += secondhalf; fifo->head += secondhalf; - // No need to check for wrap since we can not get to end of fifo in this part + /* No need to check for wrap since we can not get to end of + * the fifo in this part + */ } finish_write: spin_unlock_irqrestore(&edge_port->ep_lock, flags); - send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port); + send_more_port_data((struct edgeport_serial *) + usb_get_serial_data(port->serial), edge_port); - dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, copySize, edge_port->txCredits, fifo->count); + dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, + copySize, edge_port->txCredits, fifo->count); - return copySize; + return copySize; } @@ -1197,7 +1269,8 @@ finish_write: * can transmit more. * ************************************************************************/ -static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port) +static void send_more_port_data(struct edgeport_serial *edge_serial, + struct edgeport_port *edge_port) { struct TxFifo *fifo = &edge_port->txfifo; struct urb *urb; @@ -1216,67 +1289,78 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge if (edge_port->write_in_progress || !edge_port->open || (fifo->count == 0)) { - dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __func__, edge_port->port->number, fifo->count, edge_port->write_in_progress); + dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", + __func__, edge_port->port->number, + fifo->count, edge_port->write_in_progress); goto exit_send; } - // since the amount of data in the fifo will always fit into the - // edgeport buffer we do not need to check the write length - - // Do we have enough credits for this port to make it worthwhile - // to bother queueing a write. If it's too small, say a few bytes, - // it's better to wait for more credits so we can do a larger - // write. - if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) { - dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __func__, edge_port->port->number, fifo->count, edge_port->txCredits ); + /* since the amount of data in the fifo will always fit into the + * edgeport buffer we do not need to check the write length + * + * Do we have enough credits for this port to make it worthwhile + * to bother queueing a write. If it's too small, say a few bytes, + * it's better to wait for more credits so we can do a larger write. + */ + if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) { + dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", + __func__, edge_port->port->number, fifo->count, + edge_port->txCredits); goto exit_send; } - // lock this write + /* lock this write */ edge_port->write_in_progress = true; - // get a pointer to the write_urb + /* get a pointer to the write_urb */ urb = edge_port->write_urb; /* make sure transfer buffer is freed */ kfree(urb->transfer_buffer); urb->transfer_buffer = NULL; - /* build the data header for the buffer and port that we are about to send out */ + /* build the data header for the buffer and port that we are about + to send out */ count = fifo->count; - buffer = kmalloc (count+2, GFP_ATOMIC); + buffer = kmalloc(count+2, GFP_ATOMIC); if (buffer == NULL) { - dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __func__); + dev_err(&edge_port->port->dev, + "%s - no more kernel memory...\n", __func__); edge_port->write_in_progress = false; goto exit_send; } - buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count); - buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number - edge_port->port->serial->minor, count); + buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->number + - edge_port->port->serial->minor, count); + buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->number + - edge_port->port->serial->minor, count); /* now copy our data */ bytesleft = fifo->size - fifo->tail; - firsthalf = min (bytesleft, count); + firsthalf = min(bytesleft, count); memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf); fifo->tail += firsthalf; fifo->count -= firsthalf; - if (fifo->tail == fifo->size) { + if (fifo->tail == fifo->size) fifo->tail = 0; - } secondhalf = count-firsthalf; if (secondhalf) { - memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf); + memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], + secondhalf); fifo->tail += secondhalf; fifo->count -= secondhalf; } if (count) - usb_serial_debug_data(debug, &edge_port->port->dev, __func__, count, &buffer[2]); + usb_serial_debug_data(debug, &edge_port->port->dev, + __func__, count, &buffer[2]); /* fill up the urb with all of our data and submit it */ - usb_fill_bulk_urb (urb, edge_serial->serial->dev, - usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint), - buffer, count+2, edge_bulk_out_data_callback, edge_port); + usb_fill_bulk_urb(urb, edge_serial->serial->dev, + usb_sndbulkpipe(edge_serial->serial->dev, + edge_serial->bulk_out_endpoint), + buffer, count+2, + edge_bulk_out_data_callback, edge_port); /* decrement the number of credits we have by the number we just sent */ edge_port->txCredits -= count; @@ -1286,14 +1370,17 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { /* something went wrong */ - dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status); + dev_err(&edge_port->port->dev, + "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", + __func__, status); edge_port->write_in_progress = false; /* revert the credits as something bad happened. */ edge_port->txCredits += count; edge_port->icount.tx -= count; } - dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __func__, count, edge_port->txCredits, fifo->count); + dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", + __func__, count, edge_port->txCredits, fifo->count); exit_send: spin_unlock_irqrestore(&edge_port->ep_lock, flags); @@ -1302,14 +1389,14 @@ exit_send: /***************************************************************************** * edge_write_room - * this function is called by the tty driver when it wants to know how many - * bytes of data we can accept for a specific port. - * If successful, we return the amount of room that we have for this port - * (the txCredits), - * Otherwise we return a negative error number. + * this function is called by the tty driver when it wants to know how + * many bytes of data we can accept for a specific port. If successful, + * we return the amount of room that we have for this port (the txCredits) + * otherwise we return a negative error number. *****************************************************************************/ -static int edge_write_room (struct usb_serial_port *port) +static int edge_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); int room; unsigned long flags; @@ -1317,18 +1404,18 @@ static int edge_write_room (struct usb_serial_port *port) dbg("%s", __func__); if (edge_port == NULL) - return -ENODEV; + return 0; if (edge_port->closePending) - return -ENODEV; + return 0; dbg("%s - port %d", __func__, port->number); if (!edge_port->open) { dbg("%s - port not opened", __func__); - return -EINVAL; + return 0; } - // total of both buffers is still txCredit + /* total of both buffers is still txCredit */ spin_lock_irqsave(&edge_port->ep_lock, flags); room = edge_port->txCredits - edge_port->txfifo.count; spin_unlock_irqrestore(&edge_port->ep_lock, flags); @@ -1340,15 +1427,16 @@ static int edge_write_room (struct usb_serial_port *port) /***************************************************************************** * edge_chars_in_buffer - * this function is called by the tty driver when it wants to know how many - * bytes of data we currently have outstanding in the port (data that has - * been written, but hasn't made it out the port yet) - * If successful, we return the number of bytes left to be written in the - * system, + * this function is called by the tty driver when it wants to know how + * many bytes of data we currently have outstanding in the port (data that + * has been written, but hasn't made it out the port yet) + * If successful, we return the number of bytes left to be written in the + * system, * Otherwise we return a negative error number. *****************************************************************************/ -static int edge_chars_in_buffer (struct usb_serial_port *port) +static int edge_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); int num_chars; unsigned long flags; @@ -1356,20 +1444,22 @@ static int edge_chars_in_buffer (struct usb_serial_port *port) dbg("%s", __func__); if (edge_port == NULL) - return -ENODEV; + return 0; if (edge_port->closePending) - return -ENODEV; + return 0; if (!edge_port->open) { dbg("%s - port not opened", __func__); - return -EINVAL; + return 0; } spin_lock_irqsave(&edge_port->ep_lock, flags); - num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count; + num_chars = edge_port->maxTxCredits - edge_port->txCredits + + edge_port->txfifo.count; spin_unlock_irqrestore(&edge_port->ep_lock, flags); if (num_chars) { - dbg("%s(port %d) - returns %d", __func__, port->number, num_chars); + dbg("%s(port %d) - returns %d", __func__, + port->number, num_chars); } return num_chars; @@ -1381,10 +1471,10 @@ static int edge_chars_in_buffer (struct usb_serial_port *port) * this function is called by the tty driver when it wants to stop the data * being read from the port. *****************************************************************************/ -static void edge_throttle (struct usb_serial_port *port) +static void edge_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct tty_struct *tty; int status; dbg("%s - port %d", __func__, port->number); @@ -1397,28 +1487,21 @@ static void edge_throttle (struct usb_serial_port *port) return; } - tty = port->tty; - if (!tty) { - dbg ("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = edge_write (port, &stop_char, 1); - if (status <= 0) { + status = edge_write(tty, port, &stop_char, 1); + if (status <= 0) return; - } } /* if we are implementing RTS/CTS, toggle that line */ if (tty->termios->c_cflag & CRTSCTS) { edge_port->shadowMCR &= ~MCR_RTS; - status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); - if (status != 0) { + status = send_cmd_write_uart_register(edge_port, MCR, + edge_port->shadowMCR); + if (status != 0) return; - } } return; @@ -1427,13 +1510,13 @@ static void edge_throttle (struct usb_serial_port *port) /***************************************************************************** * edge_unthrottle - * this function is called by the tty driver when it wants to resume the data - * being read from the port (called after SerialThrottle is called) + * this function is called by the tty driver when it wants to resume the + * data being read from the port (called after SerialThrottle is called) *****************************************************************************/ -static void edge_unthrottle (struct usb_serial_port *port) +static void edge_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct tty_struct *tty; int status; dbg("%s - port %d", __func__, port->number); @@ -1446,43 +1529,31 @@ static void edge_unthrottle (struct usb_serial_port *port) return; } - tty = port->tty; - if (!tty) { - dbg ("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = edge_write (port, &start_char, 1); - if (status <= 0) { + status = edge_write(tty, port, &start_char, 1); + if (status <= 0) return; - } } - /* if we are implementing RTS/CTS, toggle that line */ if (tty->termios->c_cflag & CRTSCTS) { edge_port->shadowMCR |= MCR_RTS; - status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); - if (status != 0) { - return; - } + send_cmd_write_uart_register(edge_port, MCR, + edge_port->shadowMCR); } - - return; } /***************************************************************************** * SerialSetTermios - * this function is called by the tty driver when it wants to change the termios structure + * this function is called by the tty driver when it wants to change + * the termios structure *****************************************************************************/ -static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) +static void edge_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { - /* FIXME: This function appears unused ?? */ struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct tty_struct *tty = port->tty; unsigned int cflag; cflag = tty->termios->c_cflag; @@ -1502,9 +1573,7 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old } /* change the port settings to the new ones specified */ - change_port_settings (edge_port, old_termios); - - return; + change_port_settings(tty, edge_port, old_termios); } @@ -1516,9 +1585,10 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old * release the bus after transmitting. This must be done when * the transmit shift register is empty, not be done when the * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. + * allows an RS485 driver to be written in user space. *****************************************************************************/ -static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value) +static int get_lsr_info(struct edgeport_port *edge_port, + unsigned int __user *value) { unsigned int result = 0; unsigned long flags; @@ -1536,25 +1606,10 @@ static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *va return 0; } -static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value) -{ - unsigned int result = 0; - struct tty_struct *tty = edge_port->port->tty; - - if (!tty) - return -ENOIOCTLCMD; - - result = tty->read_cnt; - - dbg("%s(%d) = %d", __func__, edge_port->port->number, result); - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - //return 0; - return -ENOIOCTLCMD; -} - -static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) +static int edge_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int mcr; @@ -1582,8 +1637,9 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig return 0; } -static int edge_tiocmget(struct usb_serial_port *port, struct file *file) +static int edge_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int result = 0; unsigned int msr; @@ -1606,7 +1662,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file) return result; } -static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) +static int get_serial_info(struct edgeport_port *edge_port, + struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -1624,9 +1681,6 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct tmp.baud_base = 9600; tmp.close_delay = 5*HZ; tmp.closing_wait = 30*HZ; -// tmp.custom_divisor = state->custom_divisor; -// tmp.hub6 = state->hub6; -// tmp.io_type = state->io_type; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -1639,8 +1693,10 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * SerialIoctl * this function handles any ioctl calls to the driver *****************************************************************************/ -static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) +static int edge_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; DEFINE_WAIT(wait); struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct async_icount cnow; @@ -1650,71 +1706,61 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); switch (cmd) { - // return number of bytes available - case TIOCINQ: - dbg("%s (%d) TIOCINQ", __func__, port->number); - return get_number_bytes_avail(edge_port, (unsigned int __user *) arg); - break; - - case TIOCSERGETLSR: - dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); - return get_lsr_info(edge_port, (unsigned int __user *) arg); - return 0; - - case TIOCGSERIAL: - dbg("%s (%d) TIOCGSERIAL", __func__, port->number); - return get_serial_info(edge_port, (struct serial_struct __user *) arg); - - case TIOCSSERIAL: - dbg("%s (%d) TIOCSSERIAL", __func__, port->number); - break; - - case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); - cprev = edge_port->icount; - while (1) { - prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE); - schedule(); - finish_wait(&edge_port->delta_msr_wait, &wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - cnow = edge_port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; + case TIOCSERGETLSR: + dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); + return get_lsr_info(edge_port, (unsigned int __user *) arg); + + case TIOCGSERIAL: + dbg("%s (%d) TIOCGSERIAL", __func__, port->number); + return get_serial_info(edge_port, (struct serial_struct __user *) arg); + + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + cprev = edge_port->icount; + while (1) { + prepare_to_wait(&edge_port->delta_msr_wait, + &wait, TASK_INTERRUPTIBLE); + schedule(); + finish_wait(&edge_port->delta_msr_wait, &wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + cnow = edge_port->icount; + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + return 0; } - /* NOTREACHED */ - break; + cprev = cnow; + } + /* NOTREACHED */ + break; - case TIOCGICOUNT: - cnow = edge_port->icount; - memset(&icount, 0, sizeof(icount)); - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, icount.rx, icount.tx ); - if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) - return -EFAULT; - return 0; + case TIOCGICOUNT: + cnow = edge_port->icount; + memset(&icount, 0, sizeof(icount)); + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", + __func__, port->number, icount.rx, icount.tx); + if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) + return -EFAULT; + return 0; } - return -ENOIOCTLCMD; } @@ -1723,8 +1769,9 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned * SerialBreak * this function sends a break to the port *****************************************************************************/ -static void edge_break (struct usb_serial_port *port, int break_state) +static void edge_break(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial); int status; @@ -1736,9 +1783,9 @@ static void edge_break (struct usb_serial_port *port, int break_state) edge_port->chaseResponsePending = true; dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); + status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0); if (status == 0) { - // block until chase finished + /* block until chase finished */ block_until_chase_response(edge_port); } else { edge_port->chaseResponsePending = false; @@ -1750,14 +1797,16 @@ static void edge_break (struct usb_serial_port *port, int break_state) (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) { if (break_state == -1) { dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0); + status = send_iosp_ext_cmd(edge_port, + IOSP_CMD_SET_BREAK, 0); } else { dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0); - } - if (status) { - dbg("%s - error sending break set/clear command.", __func__); + status = send_iosp_ext_cmd(edge_port, + IOSP_CMD_CLEAR_BREAK, 0); } + if (status) + dbg("%s - error sending break set/clear command.", + __func__); } return; @@ -1768,7 +1817,8 @@ static void edge_break (struct usb_serial_port *port, int break_state) * process_rcvd_data * this function handles the data received on the bulk in pipe. *****************************************************************************/ -static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength) +static void process_rcvd_data(struct edgeport_serial *edge_serial, + unsigned char *buffer, __u16 bufferLength) { struct usb_serial_port *port; struct edgeport_port *edge_port; @@ -1789,105 +1839,123 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha lastBufferLength = bufferLength; switch (edge_serial->rxState) { - case EXPECT_HDR1: - edge_serial->rxHeader1 = *buffer; - ++buffer; - --bufferLength; + case EXPECT_HDR1: + edge_serial->rxHeader1 = *buffer; + ++buffer; + --bufferLength; - if (bufferLength == 0) { - edge_serial->rxState = EXPECT_HDR2; + if (bufferLength == 0) { + edge_serial->rxState = EXPECT_HDR2; + break; + } + /* otherwise, drop on through */ + case EXPECT_HDR2: + edge_serial->rxHeader2 = *buffer; + ++buffer; + --bufferLength; + + dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, + edge_serial->rxHeader1, edge_serial->rxHeader2); + /* Process depending on whether this header is + * data or status */ + + if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) { + /* Decode this status header and go to + * EXPECT_HDR1 (if we can process the status + * with only 2 bytes), or go to EXPECT_HDR3 to + * get the third byte. */ + edge_serial->rxPort = + IOSP_GET_HDR_PORT(edge_serial->rxHeader1); + edge_serial->rxStatusCode = + IOSP_GET_STATUS_CODE( + edge_serial->rxHeader1); + + if (!IOSP_STATUS_IS_2BYTE( + edge_serial->rxStatusCode)) { + /* This status needs additional bytes. + * Save what we have and then wait for + * more data. + */ + edge_serial->rxStatusParam + = edge_serial->rxHeader2; + edge_serial->rxState = EXPECT_HDR3; break; } - /* otherwise, drop on through */ - - case EXPECT_HDR2: - edge_serial->rxHeader2 = *buffer; - ++buffer; - --bufferLength; - - dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2); - - // Process depending on whether this header is - // data or status - - if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) { - // Decode this status header and goto EXPECT_HDR1 (if we - // can process the status with only 2 bytes), or goto - // EXPECT_HDR3 to get the third byte. - - edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1); - edge_serial->rxStatusCode = IOSP_GET_STATUS_CODE(edge_serial->rxHeader1); - - if (!IOSP_STATUS_IS_2BYTE(edge_serial->rxStatusCode)) { - // This status needs additional bytes. Save what we have - // and then wait for more data. - edge_serial->rxStatusParam = edge_serial->rxHeader2; - - edge_serial->rxState = EXPECT_HDR3; - break; - } + /* We have all the header bytes, process the + status now */ + process_rcvd_status(edge_serial, + edge_serial->rxHeader2, 0); + edge_serial->rxState = EXPECT_HDR1; + break; + } else { + edge_serial->rxPort = + IOSP_GET_HDR_PORT(edge_serial->rxHeader1); + edge_serial->rxBytesRemaining = + IOSP_GET_HDR_DATA_LEN( + edge_serial->rxHeader1, + edge_serial->rxHeader2); + dbg("%s - Data for Port %u Len %u", + __func__, + edge_serial->rxPort, + edge_serial->rxBytesRemaining); + + /* ASSERT(DevExt->RxPort < DevExt->NumPorts); + * ASSERT(DevExt->RxBytesRemaining < + * IOSP_MAX_DATA_LENGTH); + */ - // We have all the header bytes, process the status now - process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0); - edge_serial->rxState = EXPECT_HDR1; + if (bufferLength == 0) { + edge_serial->rxState = EXPECT_DATA; break; - } else { - edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1); - edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2); - - dbg("%s - Data for Port %u Len %u", __func__, edge_serial->rxPort, edge_serial->rxBytesRemaining); - - //ASSERT( DevExt->RxPort < DevExt->NumPorts ); - //ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH ); - - if (bufferLength == 0 ) { - edge_serial->rxState = EXPECT_DATA; - break; - } - // Else, drop through } + /* Else, drop through */ + } + case EXPECT_DATA: /* Expect data */ + if (bufferLength < edge_serial->rxBytesRemaining) { + rxLen = bufferLength; + /* Expect data to start next buffer */ + edge_serial->rxState = EXPECT_DATA; + } else { + /* BufLen >= RxBytesRemaining */ + rxLen = edge_serial->rxBytesRemaining; + /* Start another header next time */ + edge_serial->rxState = EXPECT_HDR1; + } - case EXPECT_DATA: // Expect data - - if (bufferLength < edge_serial->rxBytesRemaining) { - rxLen = bufferLength; - edge_serial->rxState = EXPECT_DATA; // Expect data to start next buffer - } else { - // BufLen >= RxBytesRemaining - rxLen = edge_serial->rxBytesRemaining; - edge_serial->rxState = EXPECT_HDR1; // Start another header next time - } + bufferLength -= rxLen; + edge_serial->rxBytesRemaining -= rxLen; - bufferLength -= rxLen; - edge_serial->rxBytesRemaining -= rxLen; - - /* spit this data back into the tty driver if this port is open */ - if (rxLen) { - port = edge_serial->serial->port[edge_serial->rxPort]; - edge_port = usb_get_serial_port_data(port); - if (edge_port->open) { - tty = edge_port->port->tty; - if (tty) { - dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort); - edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); - } - edge_port->icount.rx += rxLen; + /* spit this data back into the tty driver if this + port is open */ + if (rxLen) { + port = edge_serial->serial->port[ + edge_serial->rxPort]; + edge_port = usb_get_serial_port_data(port); + if (edge_port->open) { + tty = edge_port->port->port.tty; + if (tty) { + dbg("%s - Sending %d bytes to TTY for port %d", + __func__, rxLen, edge_serial->rxPort); + edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); } - buffer += rxLen; + edge_port->icount.rx += rxLen; } + buffer += rxLen; + } + break; - break; - - case EXPECT_HDR3: // Expect 3rd byte of status header - edge_serial->rxHeader3 = *buffer; - ++buffer; - --bufferLength; - - // We have all the header bytes, process the status now - process_rcvd_status (edge_serial, edge_serial->rxStatusParam, edge_serial->rxHeader3); - edge_serial->rxState = EXPECT_HDR1; - break; - + case EXPECT_HDR3: /* Expect 3rd byte of status header */ + edge_serial->rxHeader3 = *buffer; + ++buffer; + --bufferLength; + + /* We have all the header bytes, process the + status now */ + process_rcvd_status(edge_serial, + edge_serial->rxStatusParam, + edge_serial->rxHeader3); + edge_serial->rxState = EXPECT_HDR1; + break; } } } @@ -1895,9 +1963,11 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha /***************************************************************************** * process_rcvd_status - * this function handles the any status messages received on the bulk in pipe. + * this function handles the any status messages received on the + * bulk in pipe. *****************************************************************************/ -static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3) +static void process_rcvd_status(struct edgeport_serial *edge_serial, + __u8 byte2, __u8 byte3) { struct usb_serial_port *port; struct edgeport_port *edge_port; @@ -1907,7 +1977,9 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 port = edge_serial->serial->port[edge_serial->rxPort]; edge_port = usb_get_serial_port_data(port); if (edge_port == NULL) { - dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __func__, edge_serial->rxPort); + dev_err(&edge_serial->serial->dev->dev, + "%s - edge_port == NULL for port %d\n", + __func__, edge_serial->rxPort); return; } @@ -1915,22 +1987,28 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 if (code == IOSP_EXT_STATUS) { switch (byte2) { - case IOSP_EXT_STATUS_CHASE_RSP: - // we want to do EXT status regardless of port open/closed - dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __func__, edge_serial->rxPort, byte3 ); - // Currently, the only EXT_STATUS is Chase, so process here instead of one more call - // to one more subroutine. If/when more EXT_STATUS, there'll be more work to do. - // Also, we currently clear flag and close the port regardless of content of above's Byte3. - // We could choose to do something else when Byte3 says Timeout on Chase from Edgeport, - // like wait longer in block_until_chase_response, but for now we don't. - edge_port->chaseResponsePending = false; - wake_up (&edge_port->wait_chase); - return; + case IOSP_EXT_STATUS_CHASE_RSP: + /* we want to do EXT status regardless of port + * open/closed */ + dbg("%s - Port %u EXT CHASE_RSP Data = %02x", + __func__, edge_serial->rxPort, byte3); + /* Currently, the only EXT_STATUS is Chase, so process + * here instead of one more call to one more subroutine + * If/when more EXT_STATUS, there'll be more work to do + * Also, we currently clear flag and close the port + * regardless of content of above's Byte3. + * We could choose to do something else when Byte3 says + * Timeout on Chase from Edgeport, like wait longer in + * block_until_chase_response, but for now we don't. + */ + edge_port->chaseResponsePending = false; + wake_up(&edge_port->wait_chase); + return; - case IOSP_EXT_STATUS_RX_CHECK_RSP: - dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3 ); - //Port->RxCheckRsp = true; - return; + case IOSP_EXT_STATUS_RX_CHECK_RSP: + dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3); + /* Port->RxCheckRsp = true; */ + return; } } @@ -1938,11 +2016,14 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3); edge_port->maxTxCredits = edge_port->txCredits; dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits); - handle_new_msr (edge_port, byte2); + handle_new_msr(edge_port, byte2); - /* send the current line settings to the port so we are in sync with any further termios calls */ - if (edge_port->port->tty) - change_port_settings (edge_port, edge_port->port->tty->termios); + /* send the current line settings to the port so we are + in sync with any further termios calls */ + /* FIXME: locking on tty */ + if (edge_port->port->port.tty) + change_port_settings(edge_port->port->port.tty, + edge_port, edge_port->port->port.tty->termios); /* we have completed the open */ edge_port->openPending = false; @@ -1951,45 +2032,49 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 return; } - // If port is closed, silently discard all rcvd status. We can - // have cases where buffered status is received AFTER the close - // port command is sent to the Edgeport. - if (!edge_port->open || edge_port->closePending) { + /* If port is closed, silently discard all rcvd status. We can + * have cases where buffered status is received AFTER the close + * port command is sent to the Edgeport. + */ + if (!edge_port->open || edge_port->closePending) return; - } switch (code) { - // Not currently sent by Edgeport - case IOSP_STATUS_LSR: - dbg("%s - Port %u LSR Status = %02x", __func__, edge_serial->rxPort, byte2); - handle_new_lsr(edge_port, false, byte2, 0); - break; + /* Not currently sent by Edgeport */ + case IOSP_STATUS_LSR: + dbg("%s - Port %u LSR Status = %02x", + __func__, edge_serial->rxPort, byte2); + handle_new_lsr(edge_port, false, byte2, 0); + break; - case IOSP_STATUS_LSR_DATA: - dbg("%s - Port %u LSR Status = %02x, Data = %02x", __func__, edge_serial->rxPort, byte2, byte3); - // byte2 is LSR Register - // byte3 is broken data byte - handle_new_lsr(edge_port, true, byte2, byte3); - break; - // - // case IOSP_EXT_4_STATUS: - // dbg("%s - Port %u LSR Status = %02x Data = %02x", __func__, edge_serial->rxPort, byte2, byte3); - // break; - // - case IOSP_STATUS_MSR: - dbg("%s - Port %u MSR Status = %02x", __func__, edge_serial->rxPort, byte2); - - // Process this new modem status and generate appropriate - // events, etc, based on the new status. This routine - // also saves the MSR in Port->ShadowMsr. - handle_new_msr(edge_port, byte2); - break; + case IOSP_STATUS_LSR_DATA: + dbg("%s - Port %u LSR Status = %02x, Data = %02x", + __func__, edge_serial->rxPort, byte2, byte3); + /* byte2 is LSR Register */ + /* byte3 is broken data byte */ + handle_new_lsr(edge_port, true, byte2, byte3); + break; + /* + * case IOSP_EXT_4_STATUS: + * dbg("%s - Port %u LSR Status = %02x Data = %02x", + * __func__, edge_serial->rxPort, byte2, byte3); + * break; + */ + case IOSP_STATUS_MSR: + dbg("%s - Port %u MSR Status = %02x", + __func__, edge_serial->rxPort, byte2); + /* + * Process this new modem status and generate appropriate + * events, etc, based on the new status. This routine + * also saves the MSR in Port->ShadowMsr. + */ + handle_new_msr(edge_port, byte2); + break; - default: - dbg("%s - Unrecognized IOSP status code %u\n", __func__, code); - break; + default: + dbg("%s - Unrecognized IOSP status code %u\n", __func__, code); + break; } - return; } @@ -1998,7 +2083,8 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 * edge_tty_recv * this function passes data on to the tty flip buffer *****************************************************************************/ -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) +static void edge_tty_recv(struct device *dev, struct tty_struct *tty, + unsigned char *data, int length) { int cnt; @@ -2007,7 +2093,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c if (cnt < length) { dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt); - if(cnt == 0) + if (cnt == 0) break; } tty_insert_flip_string(tty, data, cnt); @@ -2029,22 +2115,19 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) dbg("%s %02x", __func__, newMsr); - if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { + if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | + EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { icount = &edge_port->icount; /* update input line counters */ - if (newMsr & EDGEPORT_MSR_DELTA_CTS) { + if (newMsr & EDGEPORT_MSR_DELTA_CTS) icount->cts++; - } - if (newMsr & EDGEPORT_MSR_DELTA_DSR) { + if (newMsr & EDGEPORT_MSR_DELTA_DSR) icount->dsr++; - } - if (newMsr & EDGEPORT_MSR_DELTA_CD) { + if (newMsr & EDGEPORT_MSR_DELTA_CD) icount->dcd++; - } - if (newMsr & EDGEPORT_MSR_DELTA_RI) { + if (newMsr & EDGEPORT_MSR_DELTA_RI) icount->rng++; - } wake_up_interruptible(&edge_port->delta_msr_wait); } @@ -2059,42 +2142,41 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) * handle_new_lsr * this function handles any change to the lsr register for a port. *****************************************************************************/ -static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data) +static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, + __u8 lsr, __u8 data) { - __u8 newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); - struct async_icount *icount; + __u8 newLsr = (__u8) (lsr & (__u8) + (LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); + struct async_icount *icount; dbg("%s - %02x", __func__, newLsr); edge_port->shadowLSR = lsr; if (newLsr & LSR_BREAK) { - // - // Parity and Framing errors only count if they - // occur exclusive of a break being - // received. - // + /* + * Parity and Framing errors only count if they + * occur exclusive of a break being + * received. + */ newLsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); } /* Place LSR data byte into Rx buffer */ - if (lsrData && edge_port->port->tty) - edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1); + if (lsrData && edge_port->port->port.tty) + edge_tty_recv(&edge_port->port->dev, + edge_port->port->port.tty, &data, 1); /* update input line counters */ icount = &edge_port->icount; - if (newLsr & LSR_BREAK) { + if (newLsr & LSR_BREAK) icount->brk++; - } - if (newLsr & LSR_OVER_ERR) { + if (newLsr & LSR_OVER_ERR) icount->overrun++; - } - if (newLsr & LSR_PAR_ERR) { + if (newLsr & LSR_PAR_ERR) icount->parity++; - } - if (newLsr & LSR_FRM_ERR) { + if (newLsr & LSR_FRM_ERR) icount->frame++; - } return; } @@ -2102,12 +2184,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 l /**************************************************************************** * sram_write - * writes a number of bytes to the Edgeport device's sram starting at the + * writes a number of bytes to the Edgeport device's sram starting at the * given address. * If successful returns the number of bytes written, otherwise it returns * a negative error number of the problem. ****************************************************************************/ -static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data) +static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, + __u16 length, const __u8 *data) { int result; __u16 current_length; @@ -2115,32 +2198,37 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1 dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); - transfer_buffer = kmalloc (64, GFP_KERNEL); + transfer_buffer = kmalloc(64, GFP_KERNEL); if (!transfer_buffer) { - dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64); + dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", + __func__, 64); return -ENOMEM; } /* need to split these writes up into 64 byte chunks */ result = 0; while (length > 0) { - if (length > 64) { + if (length > 64) current_length = 64; - } else { + else current_length = length; - } -// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length); - memcpy (transfer_buffer, data, current_length); - result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM, - 0x40, addr, extAddr, transfer_buffer, current_length, 300); + +/* dbg("%s - writing %x, %x, %d", __func__, + extAddr, addr, current_length); */ + memcpy(transfer_buffer, data, current_length); + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + USB_REQUEST_ION_WRITE_RAM, + 0x40, addr, extAddr, transfer_buffer, + current_length, 300); if (result < 0) break; length -= current_length; addr += current_length; data += current_length; - } + } - kfree (transfer_buffer); + kfree(transfer_buffer); return result; } @@ -2152,40 +2240,45 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1 * If successful returns the number of bytes written, otherwise it returns * a negative error number of the problem. ****************************************************************************/ -static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data) +static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, + __u16 length, const __u8 *data) { int result; __u16 current_length; unsigned char *transfer_buffer; -// dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); +/* dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); */ - transfer_buffer = kmalloc (64, GFP_KERNEL); + transfer_buffer = kmalloc(64, GFP_KERNEL); if (!transfer_buffer) { - dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64); + dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", + __func__, 64); return -ENOMEM; } /* need to split these writes up into 64 byte chunks */ result = 0; while (length > 0) { - if (length > 64) { + if (length > 64) current_length = 64; - } else { + else current_length = length; - } -// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length); - memcpy (transfer_buffer, data, current_length); - result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM, - 0x40, addr, extAddr, transfer_buffer, current_length, 300); +/* dbg("%s - writing %x, %x, %d", __func__, + extAddr, addr, current_length); */ + memcpy(transfer_buffer, data, current_length); + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + USB_REQUEST_ION_WRITE_ROM, 0x40, + addr, extAddr, + transfer_buffer, current_length, 300); if (result < 0) break; length -= current_length; addr += current_length; data += current_length; - } + } - kfree (transfer_buffer); + kfree(transfer_buffer); return result; } @@ -2197,7 +2290,8 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 * If successful returns the number of bytes read, otherwise it returns * a negative error number of the problem. ****************************************************************************/ -static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data) +static int rom_read(struct usb_serial *serial, __u16 extAddr, + __u16 addr, __u16 length, __u8 *data) { int result; __u16 current_length; @@ -2205,32 +2299,36 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); - transfer_buffer = kmalloc (64, GFP_KERNEL); + transfer_buffer = kmalloc(64, GFP_KERNEL); if (!transfer_buffer) { - dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64); + dev_err(&serial->dev->dev, + "%s - kmalloc(%d) failed.\n", __func__, 64); return -ENOMEM; } /* need to split these reads up into 64 byte chunks */ result = 0; while (length > 0) { - if (length > 64) { + if (length > 64) current_length = 64; - } else { + else current_length = length; - } -// dbg("%s - %x, %x, %d", __func__, extAddr, addr, current_length); - result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM, - 0xC0, addr, extAddr, transfer_buffer, current_length, 300); +/* dbg("%s - %x, %x, %d", __func__, + extAddr, addr, current_length); */ + result = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + USB_REQUEST_ION_READ_ROM, + 0xC0, addr, extAddr, transfer_buffer, + current_length, 300); if (result < 0) break; - memcpy (data, transfer_buffer, current_length); + memcpy(data, transfer_buffer, current_length); length -= current_length; addr += current_length; data += current_length; - } + } - kfree (transfer_buffer); + kfree(transfer_buffer); return result; } @@ -2239,7 +2337,8 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 * send_iosp_ext_cmd * Is used to send a IOSP message to the Edgeport device ****************************************************************************/ -static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param) +static int send_iosp_ext_cmd(struct edgeport_port *edge_port, + __u8 command, __u8 param) { unsigned char *buffer; unsigned char *currentCommand; @@ -2248,19 +2347,20 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u dbg("%s - %d, %d", __func__, command, param); - buffer = kmalloc (10, GFP_ATOMIC); + buffer = kmalloc(10, GFP_ATOMIC); if (!buffer) { - dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 10); + dev_err(&edge_port->port->dev, + "%s - kmalloc(%d) failed.\n", __func__, 10); return -ENOMEM; } currentCommand = buffer; - MAKE_CMD_EXT_CMD (¤tCommand, &length, - edge_port->port->number - edge_port->port->serial->minor, - command, param); + MAKE_CMD_EXT_CMD(¤tCommand, &length, + edge_port->port->number - edge_port->port->serial->minor, + command, param); - status = write_cmd_usb (edge_port, buffer, length); + status = write_cmd_usb(edge_port, buffer, length); if (status) { /* something bad happened, let's free up the memory */ kfree(buffer); @@ -2274,43 +2374,50 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u * write_cmd_usb * this function writes the given buffer out to the bulk write endpoint. *****************************************************************************/ -static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int length) +static int write_cmd_usb(struct edgeport_port *edge_port, + unsigned char *buffer, int length) { - struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); + struct edgeport_serial *edge_serial = + usb_get_serial_data(edge_port->port->serial); int status = 0; struct urb *urb; int timeout; - usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer); + usb_serial_debug_data(debug, &edge_port->port->dev, + __func__, length, buffer); /* Allocate our next urb */ - urb = usb_alloc_urb (0, GFP_ATOMIC); + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; atomic_inc(&CmdUrbs); - dbg("%s - ALLOCATE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs)); + dbg("%s - ALLOCATE URB %p (outstanding %d)", + __func__, urb, atomic_read(&CmdUrbs)); - usb_fill_bulk_urb (urb, edge_serial->serial->dev, - usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint), - buffer, length, edge_bulk_out_cmd_callback, edge_port); + usb_fill_bulk_urb(urb, edge_serial->serial->dev, + usb_sndbulkpipe(edge_serial->serial->dev, + edge_serial->bulk_out_endpoint), + buffer, length, edge_bulk_out_cmd_callback, edge_port); edge_port->commandPending = true; status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { /* something went wrong */ - dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __func__, status); + dev_err(&edge_port->port->dev, + "%s - usb_submit_urb(write command) failed, status = %d\n", + __func__, status); usb_kill_urb(urb); usb_free_urb(urb); atomic_dec(&CmdUrbs); return status; } - // wait for command to finish + /* wait for command to finish */ timeout = COMMAND_TIMEOUT; #if 0 - wait_event (&edge_port->wait_command, !edge_port->commandPending); + wait_event(&edge_port->wait_command, !edge_port->commandPending); if (edge_port->commandPending) { /* command timed out */ @@ -2327,15 +2434,18 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer * this function sends the proper command to change the baud rate of the * specified port. *****************************************************************************/ -static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate) +static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, + int baudRate) { - struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); + struct edgeport_serial *edge_serial = + usb_get_serial_data(edge_port->port->serial); unsigned char *cmdBuffer; unsigned char *currCmd; int cmdLen = 0; int divisor; int status; - unsigned char number = edge_port->port->number - edge_port->port->serial->minor; + unsigned char number = + edge_port->port->number - edge_port->port->serial->minor; if (edge_serial->is_epic && !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) { @@ -2344,36 +2454,40 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa return 0; } - dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate); + dbg("%s - port = %d, baud = %d", __func__, + edge_port->port->number, baudRate); - status = calc_baud_rate_divisor (baudRate, &divisor); + status = calc_baud_rate_divisor(baudRate, &divisor); if (status) { - dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __func__); + dev_err(&edge_port->port->dev, "%s - bad baud rate\n", + __func__); return status; } - // Alloc memory for the string of commands. - cmdBuffer = kmalloc (0x100, GFP_ATOMIC); + /* Alloc memory for the string of commands. */ + cmdBuffer = kmalloc(0x100, GFP_ATOMIC); if (!cmdBuffer) { - dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100); + dev_err(&edge_port->port->dev, + "%s - kmalloc(%d) failed.\n", __func__, 0x100); return -ENOMEM; } currCmd = cmdBuffer; - // Enable access to divisor latch - MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE ); + /* Enable access to divisor latch */ + MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE); - // Write the divisor itself - MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLL, LOW8 (divisor) ); - MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLM, HIGH8(divisor) ); + /* Write the divisor itself */ + MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLL, LOW8(divisor)); + MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLM, HIGH8(divisor)); - // Restore original value to disable access to divisor latch - MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR); + /* Restore original value to disable access to divisor latch */ + MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR, + edge_port->shadowLCR); - status = write_cmd_usb(edge_port, cmdBuffer, cmdLen ); + status = write_cmd_usb(edge_port, cmdBuffer, cmdLen); if (status) { /* something bad happened, let's free up the memory */ - kfree (cmdBuffer); + kfree(cmdBuffer); } return status; @@ -2385,7 +2499,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa * this function calculates the proper baud rate divisor for the specified * baud rate. *****************************************************************************/ -static int calc_baud_rate_divisor (int baudrate, int *divisor) +static int calc_baud_rate_divisor(int baudrate, int *divisor) { int i; __u16 custom; @@ -2394,17 +2508,17 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor) dbg("%s - %d", __func__, baudrate); for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { - if ( divisor_table[i].BaudRate == baudrate ) { + if (divisor_table[i].BaudRate == baudrate) { *divisor = divisor_table[i].Divisor; return 0; } } - // We have tried all of the standard baud rates - // lets try to calculate the divisor for this baud rate - // Make sure the baud rate is reasonable + /* We have tried all of the standard baud rates + * lets try to calculate the divisor for this baud rate + * Make sure the baud rate is reasonable */ if (baudrate > 50 && baudrate < 230400) { - // get divisor + /* get divisor */ custom = (__u16)((230400L + baudrate/2) / baudrate); *divisor = custom; @@ -2419,17 +2533,20 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor) /***************************************************************************** * send_cmd_write_uart_register - * this function builds up a uart register message and sends to to the device. + * this function builds up a uart register message and sends to to the device. *****************************************************************************/ -static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue) +static int send_cmd_write_uart_register(struct edgeport_port *edge_port, + __u8 regNum, __u8 regValue) { - struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); + struct edgeport_serial *edge_serial = + usb_get_serial_data(edge_port->port->serial); unsigned char *cmdBuffer; unsigned char *currCmd; unsigned long cmdLen = 0; int status; - dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __func__, regValue); + dbg("%s - write to %s register 0x%02x", + (regNum == MCR) ? "MCR" : "LCR", __func__, regValue); if (edge_serial->is_epic && !edge_serial->epic_descriptor.Supports.IOSPWriteMCR && @@ -2441,27 +2558,26 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r if (edge_serial->is_epic && !edge_serial->epic_descriptor.Supports.IOSPWriteLCR && regNum == LCR) { - dbg ("SendCmdWriteUartReg - Not writing to LCR Register"); + dbg("SendCmdWriteUartReg - Not writing to LCR Register"); return 0; } - // Alloc memory for the string of commands. - cmdBuffer = kmalloc (0x10, GFP_ATOMIC); - if (cmdBuffer == NULL ) { + /* Alloc memory for the string of commands. */ + cmdBuffer = kmalloc(0x10, GFP_ATOMIC); + if (cmdBuffer == NULL) return -ENOMEM; - } currCmd = cmdBuffer; - // Build a cmd in the buffer to write the given register - MAKE_CMD_WRITE_REG (&currCmd, &cmdLen, - edge_port->port->number - edge_port->port->serial->minor, - regNum, regValue); + /* Build a cmd in the buffer to write the given register */ + MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, + edge_port->port->number - edge_port->port->serial->minor, + regNum, regValue); status = write_cmd_usb(edge_port, cmdBuffer, cmdLen); if (status) { /* something bad happened, let's free up the memory */ - kfree (cmdBuffer); + kfree(cmdBuffer); } return status; @@ -2470,16 +2586,15 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r /***************************************************************************** * change_port_settings - * This routine is called to set the UART on the device to match the specified - * new settings. + * This routine is called to set the UART on the device to match the + * specified new settings. *****************************************************************************/ -#ifndef CMSPAR -#define CMSPAR 0 -#endif -static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) + +static void change_port_settings(struct tty_struct *tty, + struct edgeport_port *edge_port, struct ktermios *old_termios) { - struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); - struct tty_struct *tty; + struct edgeport_serial *edge_serial = + usb_get_serial_data(edge_port->port->serial); int baud; unsigned cflag; __u8 mask = 0xff; @@ -2498,21 +2613,26 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi return; } - tty = edge_port->port->tty; - if ((!tty) || - (!tty->termios)) { - dbg("%s - no tty structures", __func__); - return; - } - cflag = tty->termios->c_cflag; switch (cflag & CSIZE) { - case CS5: lData = LCR_BITS_5; mask = 0x1f; dbg("%s - data bits = 5", __func__); break; - case CS6: lData = LCR_BITS_6; mask = 0x3f; dbg("%s - data bits = 6", __func__); break; - case CS7: lData = LCR_BITS_7; mask = 0x7f; dbg("%s - data bits = 7", __func__); break; - default: - case CS8: lData = LCR_BITS_8; dbg("%s - data bits = 8", __func__); break; + case CS5: + lData = LCR_BITS_5; mask = 0x1f; + dbg("%s - data bits = 5", __func__); + break; + case CS6: + lData = LCR_BITS_6; mask = 0x3f; + dbg("%s - data bits = 6", __func__); + break; + case CS7: + lData = LCR_BITS_7; mask = 0x7f; + dbg("%s - data bits = 7", __func__); + break; + default: + case CS8: + lData = LCR_BITS_8; + dbg("%s - data bits = 8", __func__); + break; } lParity = LCR_PAR_NONE; @@ -2554,7 +2674,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi dbg("%s - RTS/CTS is disabled", __func__); } - /* if we are implementing XON/XOFF, set the start and stop character in the device */ + /* if we are implementing XON/XOFF, set the start and stop character + in the device */ if (I_IXOFF(tty) || I_IXON(tty)) { unsigned char stop_char = STOP_CHAR(tty); unsigned char start_char = START_CHAR(tty); @@ -2562,14 +2683,17 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi if ((!edge_serial->is_epic) || ((edge_serial->is_epic) && (edge_serial->epic_descriptor.Supports.IOSPSetXChar))) { - send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XON_CHAR, start_char); - send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char); + send_iosp_ext_cmd(edge_port, + IOSP_CMD_SET_XON_CHAR, start_char); + send_iosp_ext_cmd(edge_port, + IOSP_CMD_SET_XOFF_CHAR, stop_char); } /* if we are implementing INBOUND XON/XOFF */ if (I_IXOFF(tty)) { rxFlow |= IOSP_RX_FLOW_XON_XOFF; - dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char); + dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", + __func__, start_char, stop_char); } else { dbg("%s - INBOUND XON/XOFF is disabled", __func__); } @@ -2577,7 +2701,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi /* if we are implementing OUTBOUND XON/XOFF */ if (I_IXON(tty)) { txFlow |= IOSP_TX_FLOW_XON_XOFF; - dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char); + dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", + __func__, start_char, stop_char); } else { dbg("%s - OUTBOUND XON/XOFF is disabled", __func__); } @@ -2600,20 +2725,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi edge_port->validDataMask = mask; /* Send the updated LCR value to the EdgePort */ - status = send_cmd_write_uart_register(edge_port, LCR, edge_port->shadowLCR); - if (status != 0) { + status = send_cmd_write_uart_register(edge_port, LCR, + edge_port->shadowLCR); + if (status != 0) return; - } /* set up the MCR register and send it to the EdgePort */ edge_port->shadowMCR = MCR_MASTER_IE; - if (cflag & CBAUD) { + if (cflag & CBAUD) edge_port->shadowMCR |= (MCR_DTR | MCR_RTS); - } - status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); - if (status != 0) { + + status = send_cmd_write_uart_register(edge_port, MCR, + edge_port->shadowMCR); + if (status != 0) return; - } /* Determine divisor based on baud rate */ baud = tty_get_baud_rate(tty); @@ -2623,7 +2748,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi } dbg("%s - baud rate = %d", __func__, baud); - status = send_cmd_write_baud_rate (edge_port, baud); + status = send_cmd_write_baud_rate(edge_port, baud); if (status == -1) { /* Speed change was not possible - put back the old speed */ baud = tty_termios_baud_rate(old_termios); @@ -2640,7 +2765,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi * ASCII range, but it's only for debugging... * NOTE: expects the unicode in LE format ****************************************************************************/ -static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size) +static void unicode_to_ascii(char *string, int buflen, + __le16 *unicode, int unicode_size) { int i; @@ -2659,75 +2785,99 @@ static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unic /**************************************************************************** * get_manufacturing_desc - * reads in the manufacturing descriptor and stores it into the serial + * reads in the manufacturing descriptor and stores it into the serial * structure. ****************************************************************************/ -static void get_manufacturing_desc (struct edgeport_serial *edge_serial) +static void get_manufacturing_desc(struct edgeport_serial *edge_serial) { int response; dbg("getting manufacturer descriptor"); - response = rom_read (edge_serial->serial, (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16, - (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff), EDGE_MANUF_DESC_LEN, - (__u8 *)(&edge_serial->manuf_descriptor)); + response = rom_read(edge_serial->serial, + (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16, + (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff), + EDGE_MANUF_DESC_LEN, + (__u8 *)(&edge_serial->manuf_descriptor)); - if (response < 1) { - dev_err(&edge_serial->serial->dev->dev, "error in getting manufacturer descriptor\n"); - } else { + if (response < 1) + dev_err(&edge_serial->serial->dev->dev, + "error in getting manufacturer descriptor\n"); + else { char string[30]; dbg("**Manufacturer Descriptor"); - dbg(" RomSize: %dK", edge_serial->manuf_descriptor.RomSize); - dbg(" RamSize: %dK", edge_serial->manuf_descriptor.RamSize); - dbg(" CpuRev: %d", edge_serial->manuf_descriptor.CpuRev); - dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); - dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); - dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); + dbg(" RomSize: %dK", + edge_serial->manuf_descriptor.RomSize); + dbg(" RamSize: %dK", + edge_serial->manuf_descriptor.RamSize); + dbg(" CpuRev: %d", + edge_serial->manuf_descriptor.CpuRev); + dbg(" BoardRev: %d", + edge_serial->manuf_descriptor.BoardRev); + dbg(" NumPorts: %d", + edge_serial->manuf_descriptor.NumPorts); + dbg(" DescDate: %d/%d/%d", + edge_serial->manuf_descriptor.DescDate[0], + edge_serial->manuf_descriptor.DescDate[1], + edge_serial->manuf_descriptor.DescDate[2]+1900); unicode_to_ascii(string, sizeof(string), - edge_serial->manuf_descriptor.SerialNumber, - edge_serial->manuf_descriptor.SerNumLength/2); + edge_serial->manuf_descriptor.SerialNumber, + edge_serial->manuf_descriptor.SerNumLength/2); dbg(" SerialNumber: %s", string); unicode_to_ascii(string, sizeof(string), - edge_serial->manuf_descriptor.AssemblyNumber, - edge_serial->manuf_descriptor.AssemblyNumLength/2); + edge_serial->manuf_descriptor.AssemblyNumber, + edge_serial->manuf_descriptor.AssemblyNumLength/2); dbg(" AssemblyNumber: %s", string); unicode_to_ascii(string, sizeof(string), edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2); dbg(" OemAssyNumber: %s", string); - dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); - dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); - dbg(" IonConfig: %d", edge_serial->manuf_descriptor.IonConfig); + dbg(" UartType: %d", + edge_serial->manuf_descriptor.UartType); + dbg(" IonPid: %d", + edge_serial->manuf_descriptor.IonPid); + dbg(" IonConfig: %d", + edge_serial->manuf_descriptor.IonConfig); } } /**************************************************************************** * get_boot_desc - * reads in the bootloader descriptor and stores it into the serial + * reads in the bootloader descriptor and stores it into the serial * structure. ****************************************************************************/ -static void get_boot_desc (struct edgeport_serial *edge_serial) +static void get_boot_desc(struct edgeport_serial *edge_serial) { int response; dbg("getting boot descriptor"); - response = rom_read (edge_serial->serial, (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16, - (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff), EDGE_BOOT_DESC_LEN, - (__u8 *)(&edge_serial->boot_descriptor)); + response = rom_read(edge_serial->serial, + (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16, + (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff), + EDGE_BOOT_DESC_LEN, + (__u8 *)(&edge_serial->boot_descriptor)); - if (response < 1) { - dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n"); - } else { + if (response < 1) + dev_err(&edge_serial->serial->dev->dev, + "error in getting boot descriptor\n"); + else { dbg("**Boot Descriptor:"); - dbg(" BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); - dbg(" MajorVersion: %d", edge_serial->boot_descriptor.MajorVersion); - dbg(" MinorVersion: %d", edge_serial->boot_descriptor.MinorVersion); - dbg(" BuildNumber: %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); - dbg(" Capabilities: 0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities)); - dbg(" UConfig0: %d", edge_serial->boot_descriptor.UConfig0); - dbg(" UConfig1: %d", edge_serial->boot_descriptor.UConfig1); + dbg(" BootCodeLength: %d", + le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); + dbg(" MajorVersion: %d", + edge_serial->boot_descriptor.MajorVersion); + dbg(" MinorVersion: %d", + edge_serial->boot_descriptor.MinorVersion); + dbg(" BuildNumber: %d", + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); + dbg(" Capabilities: 0x%x", + le16_to_cpu(edge_serial->boot_descriptor.Capabilities)); + dbg(" UConfig0: %d", + edge_serial->boot_descriptor.UConfig0); + dbg(" UConfig1: %d", + edge_serial->boot_descriptor.UConfig1); } } @@ -2736,7 +2886,7 @@ static void get_boot_desc (struct edgeport_serial *edge_serial) * load_application_firmware * This is called to load the application firmware to the device ****************************************************************************/ -static void load_application_firmware (struct edgeport_serial *edge_serial) +static void load_application_firmware(struct edgeport_serial *edge_serial) { const struct ihex_binrec *rec; const struct firmware *fw; @@ -2813,7 +2963,7 @@ static void load_application_firmware (struct edgeport_serial *edge_serial) /**************************************************************************** * edge_startup ****************************************************************************/ -static int edge_startup (struct usb_serial *serial) +static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; @@ -2855,10 +3005,10 @@ static int edge_startup (struct usb_serial *serial) sizeof(struct edge_compatibility_bits)); /* get the manufacturing descriptor for this device */ - get_manufacturing_desc (edge_serial); + get_manufacturing_desc(edge_serial); /* get the boot descriptor */ - get_boot_desc (edge_serial); + get_boot_desc(edge_serial); get_product_info(edge_serial); } @@ -2879,41 +3029,43 @@ static int edge_startup (struct usb_serial *serial) /* If not an EPiC device */ if (!edge_serial->is_epic) { /* now load the application firmware into this device */ - load_application_firmware (edge_serial); + load_application_firmware(edge_serial); dbg("%s - time 2 %ld", __func__, jiffies); /* Check current Edgeport EEPROM and update if necessary */ - update_edgeport_E2PROM (edge_serial); + update_edgeport_E2PROM(edge_serial); dbg("%s - time 3 %ld", __func__, jiffies); /* set the configuration to use #1 */ -// dbg("set_configuration 1"); -// usb_set_configuration (dev, 1); +/* dbg("set_configuration 1"); */ +/* usb_set_configuration (dev, 1); */ } dbg(" FirmwareMajorVersion %d.%d.%d", edge_serial->product_info.FirmwareMajorVersion, edge_serial->product_info.FirmwareMinorVersion, le16_to_cpu(edge_serial->product_info.FirmwareBuildNumber)); - /* we set up the pointers to the endpoints in the edge_open function, + /* we set up the pointers to the endpoints in the edge_open function, * as the structures aren't created yet. */ /* set up our port private structures */ for (i = 0; i < serial->num_ports; ++i) { - edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); + edge_port = kmalloc(sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + dev_err(&serial->dev->dev, "%s - Out of memory\n", + __func__); for (j = 0; j < i; ++j) { - kfree (usb_get_serial_port_data(serial->port[j])); - usb_set_serial_port_data(serial->port[j], NULL); + kfree(usb_get_serial_port_data(serial->port[j])); + usb_set_serial_port_data(serial->port[j], + NULL); } usb_set_serial_data(serial, NULL); kfree(edge_serial); return -ENOMEM; } - memset (edge_port, 0, sizeof(struct edgeport_port)); + memset(edge_port, 0, sizeof(struct edgeport_port)); spin_lock_init(&edge_port->ep_lock); edge_port->port = serial->port[i]; usb_set_serial_port_data(serial->port[i], edge_port); @@ -2922,14 +3074,16 @@ static int edge_startup (struct usb_serial *serial) response = 0; if (edge_serial->is_epic) { - /* EPIC thing, set up our interrupt polling now and our read urb, so - * that the device knows it really is connected. */ + /* EPIC thing, set up our interrupt polling now and our read + * urb, so that the device knows it really is connected. */ interrupt_in_found = bulk_in_found = bulk_out_found = false; - for (i = 0; i < serial->interface->altsetting[0].desc.bNumEndpoints; ++i) { + for (i = 0; i < serial->interface->altsetting[0] + .desc.bNumEndpoints; ++i) { struct usb_endpoint_descriptor *endpoint; int buffer_size; - endpoint = &serial->interface->altsetting[0].endpoint[i].desc; + endpoint = &serial->interface->altsetting[0]. + endpoint[i].desc; buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); if (!interrupt_in_found && (usb_endpoint_is_int_in(endpoint))) { @@ -2937,58 +3091,67 @@ static int edge_startup (struct usb_serial *serial) dbg("found interrupt in"); /* not set up yet, so do it now */ - edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL); + edge_serial->interrupt_read_urb = + usb_alloc_urb(0, GFP_KERNEL); if (!edge_serial->interrupt_read_urb) { err("out of memory"); return -ENOMEM; } - edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); + edge_serial->interrupt_in_buffer = + kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->interrupt_in_buffer) { err("out of memory"); usb_free_urb(edge_serial->interrupt_read_urb); return -ENOMEM; } - edge_serial->interrupt_in_endpoint = endpoint->bEndpointAddress; + edge_serial->interrupt_in_endpoint = + endpoint->bEndpointAddress; /* set up our interrupt urb */ - usb_fill_int_urb(edge_serial->interrupt_read_urb, - dev, - usb_rcvintpipe(dev, endpoint->bEndpointAddress), - edge_serial->interrupt_in_buffer, - buffer_size, - edge_interrupt_callback, - edge_serial, - endpoint->bInterval); + usb_fill_int_urb( + edge_serial->interrupt_read_urb, + dev, + usb_rcvintpipe(dev, + endpoint->bEndpointAddress), + edge_serial->interrupt_in_buffer, + buffer_size, + edge_interrupt_callback, + edge_serial, + endpoint->bInterval); interrupt_in_found = true; } if (!bulk_in_found && - (usb_endpoint_is_bulk_in(endpoint))) { + (usb_endpoint_is_bulk_in(endpoint))) { /* we found a bulk in endpoint */ dbg("found bulk in"); /* not set up yet, so do it now */ - edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL); + edge_serial->read_urb = + usb_alloc_urb(0, GFP_KERNEL); if (!edge_serial->read_urb) { err("out of memory"); return -ENOMEM; } - edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); + edge_serial->bulk_in_buffer = + kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->bulk_in_buffer) { - err ("out of memory"); + err("out of memory"); usb_free_urb(edge_serial->read_urb); return -ENOMEM; } - edge_serial->bulk_in_endpoint = endpoint->bEndpointAddress; + edge_serial->bulk_in_endpoint = + endpoint->bEndpointAddress; /* set up our bulk in urb */ usb_fill_bulk_urb(edge_serial->read_urb, dev, - usb_rcvbulkpipe(dev, endpoint->bEndpointAddress), - edge_serial->bulk_in_buffer, - le16_to_cpu(endpoint->wMaxPacketSize), - edge_bulk_in_callback, - edge_serial); + usb_rcvbulkpipe(dev, + endpoint->bEndpointAddress), + edge_serial->bulk_in_buffer, + le16_to_cpu(endpoint->wMaxPacketSize), + edge_bulk_in_callback, + edge_serial); bulk_in_found = true; } @@ -2996,21 +3159,24 @@ static int edge_startup (struct usb_serial *serial) (usb_endpoint_is_bulk_out(endpoint))) { /* we found a bulk out endpoint */ dbg("found bulk out"); - edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress; + edge_serial->bulk_out_endpoint = + endpoint->bEndpointAddress; bulk_out_found = true; } } if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) { - err ("Error - the proper endpoints were not found!"); + err("Error - the proper endpoints were not found!"); return -ENODEV; } /* start interrupt read for this edgeport this interrupt will * continue as long as the edgeport is connected */ - response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL); + response = usb_submit_urb(edge_serial->interrupt_read_urb, + GFP_KERNEL); if (response) - err("%s - Error %d submitting control urb", __func__, response); + err("%s - Error %d submitting control urb", + __func__, response); } return response; } @@ -3020,7 +3186,7 @@ static int edge_startup (struct usb_serial *serial) * edge_shutdown * This function is called whenever the device is removed from the usb bus. ****************************************************************************/ -static void edge_shutdown (struct usb_serial *serial) +static void edge_shutdown(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); int i; @@ -3028,8 +3194,8 @@ static void edge_shutdown (struct usb_serial *serial) dbg("%s", __func__); /* stop reads and writes on all ports */ - for (i=0; i < serial->num_ports; ++i) { - kfree (usb_get_serial_port_data(serial->port[i])); + for (i = 0; i < serial->num_ports; ++i) { + kfree(usb_get_serial_port_data(serial->port[i])); usb_set_serial_port_data(serial->port[i], NULL); } /* free up our endpoint stuff */ @@ -3069,7 +3235,7 @@ static int __init edgeport_init(void) if (retval) goto failed_epic_device_register; retval = usb_register(&io_driver); - if (retval) + if (retval) goto failed_usb_register; atomic_set(&CmdUrbs, 0); info(DRIVER_DESC " " DRIVER_VERSION); @@ -3094,19 +3260,19 @@ failed_2port_device_register: ****************************************************************************/ static void __exit edgeport_exit (void) { - usb_deregister (&io_driver); - usb_serial_deregister (&edgeport_2port_device); - usb_serial_deregister (&edgeport_4port_device); - usb_serial_deregister (&edgeport_8port_device); - usb_serial_deregister (&epic_device); + usb_deregister(&io_driver); + usb_serial_deregister(&edgeport_2port_device); + usb_serial_deregister(&edgeport_4port_device); + usb_serial_deregister(&edgeport_8port_device); + usb_serial_deregister(&epic_device); } module_init(edgeport_init); module_exit(edgeport_exit); /* Module information */ -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("edgeport/boot.fw"); MODULE_FIRMWARE("edgeport/boot2.fw"); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 2ec85893f27a..7eb9d67b81b6 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -8,7 +8,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * */ #ifndef IO_TABLES_H @@ -90,10 +90,10 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) }, { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) }, { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) }, - { } /* Terminating entry */ + { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver io_driver = { .name = "io_edgeport", diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 61daea3f7b2d..cb4c54316cf5 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -18,8 +18,8 @@ * * Version history: * - * July 11, 2002 Removed 4 port device structure since all TI UMP - * chips have only 2 ports + * July 11, 2002 Removed 4 port device structure since all TI UMP + * chips have only 2 ports * David Iacovelli (davidi@ionetworks.com) * */ @@ -38,7 +38,7 @@ #include <linux/serial.h> #include <linux/ioctl.h> #include <linux/firmware.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -57,18 +57,19 @@ struct edgeport_uart_buf_desc { - __u32 count; // Number of bytes currently in buffer + __u32 count; /* Number of bytes currently in buffer */ }; /* different hardware types */ #define HARDWARE_TYPE_930 0 #define HARDWARE_TYPE_TIUMP 1 -// IOCTL_PRIVATE_TI_GET_MODE Definitions -#define TI_MODE_CONFIGURING 0 // Device has not entered start device -#define TI_MODE_BOOT 1 // Staying in boot mode -#define TI_MODE_DOWNLOAD 2 // Made it to download mode -#define TI_MODE_TRANSITIONING 3 // Currently in boot mode but transitioning to download mode +/* IOCTL_PRIVATE_TI_GET_MODE Definitions */ +#define TI_MODE_CONFIGURING 0 /* Device has not entered start device */ +#define TI_MODE_BOOT 1 /* Staying in boot mode */ +#define TI_MODE_DOWNLOAD 2 /* Made it to download mode */ +#define TI_MODE_TRANSITIONING 3 /* Currently in boot mode but + transitioning to download mode */ /* read urb state */ #define EDGE_READ_URB_RUNNING 0 @@ -82,10 +83,9 @@ struct edgeport_uart_buf_desc { /* Product information read from the Edgeport */ -struct product_info -{ - int TiMode; // Current TI Mode - __u8 hardware_type; // Type of hardware +struct product_info { + int TiMode; /* Current TI Mode */ + __u8 hardware_type; /* Type of hardware */ } __attribute__((packed)); /* circular buffer */ @@ -116,7 +116,7 @@ struct edgeport_port { happen */ struct edgeport_serial *edge_serial; struct usb_serial_port *port; - __u8 bUartMode; /* Port type, 0: RS232, etc. */ + __u8 bUartMode; /* Port type, 0: RS232, etc. */ spinlock_t ep_lock; int ep_read_urb_state; int ep_write_urb_in_use; @@ -125,8 +125,9 @@ struct edgeport_port { struct edgeport_serial { struct product_info product_info; - u8 TI_I2C_Type; // Type of I2C in UMP - u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode + u8 TI_I2C_Type; /* Type of I2C in UMP */ + u8 TiReadI2C; /* Set to TRUE if we have read the + I2c in Boot Mode */ struct mutex es_lock; int num_ports_open; struct usb_serial *serial; @@ -214,7 +215,7 @@ static struct usb_device_id id_table_combined [] = { { } }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver io_driver = { .name = "io_ti", @@ -231,20 +232,20 @@ static unsigned short OperationalBuildNumber; static int debug; -static int TIStayInBootMode = 0; static int low_latency = EDGE_LOW_LATENCY; static int closing_wait = EDGE_CLOSING_WAIT; -static int ignore_cpu_rev = 0; -static int default_uart_mode = 0; /* RS232 */ - +static int ignore_cpu_rev; +static int default_uart_mode; /* RS232 */ -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length); +static void edge_tty_recv(struct device *dev, struct tty_struct *tty, + unsigned char *data, int length); static void stop_read(struct edgeport_port *edge_port); static int restart_read(struct edgeport_port *edge_port); -static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); -static void edge_send(struct usb_serial_port *port); +static void edge_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios); +static void edge_send(struct tty_struct *tty); /* sysfs attributes */ static int edge_create_sysfs_attrs(struct usb_serial_port *port); @@ -262,87 +263,57 @@ static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, unsigned int count); -static int TIReadVendorRequestSync (struct usb_device *dev, - __u8 request, - __u16 value, - __u16 index, - u8 *data, - int size) +static int ti_vread_sync(struct usb_device *dev, __u8 request, + __u16 value, __u16 index, u8 *data, int size) { int status; - status = usb_control_msg (dev, - usb_rcvctrlpipe(dev, 0), - request, - (USB_TYPE_VENDOR | - USB_RECIP_DEVICE | - USB_DIR_IN), - value, - index, - data, - size, - 1000); + status = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, + (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN), + value, index, data, size, 1000); if (status < 0) return status; if (status != size) { - dbg ("%s - wanted to write %d, but only wrote %d", - __func__, size, status); + dbg("%s - wanted to write %d, but only wrote %d", + __func__, size, status); return -ECOMM; } return 0; } -static int TISendVendorRequestSync (struct usb_device *dev, - __u8 request, - __u16 value, - __u16 index, - u8 *data, - int size) +static int ti_vsend_sync(struct usb_device *dev, __u8 request, + __u16 value, __u16 index, u8 *data, int size) { int status; - status = usb_control_msg (dev, - usb_sndctrlpipe(dev, 0), - request, - (USB_TYPE_VENDOR | - USB_RECIP_DEVICE | - USB_DIR_OUT), - value, - index, - data, - size, - 1000); + status = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, + (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT), + value, index, data, size, 1000); if (status < 0) return status; if (status != size) { - dbg ("%s - wanted to write %d, but only wrote %d", + dbg("%s - wanted to write %d, but only wrote %d", __func__, size, status); return -ECOMM; } return 0; } -static int TIWriteCommandSync (struct usb_device *dev, __u8 command, +static int send_cmd(struct usb_device *dev, __u8 command, __u8 moduleid, __u16 value, u8 *data, int size) { - return TISendVendorRequestSync (dev, - command, // Request - value, // wValue - moduleid, // wIndex - data, // TransferBuffer - size); // TransferBufferLength - + return ti_vsend_sync(dev, command, value, moduleid, data, size); } /* clear tx/rx buffers and fifo in TI UMP */ -static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask) +static int purge_port(struct usb_serial_port *port, __u16 mask) { int port_number = port->number - port->serial->minor; - dbg ("%s - port %d, mask %x", __func__, port_number, mask); + dbg("%s - port %d, mask %x", __func__, port_number, mask); - return TIWriteCommandSync (port->serial->dev, + return send_cmd(port->serial->dev, UMPC_PURGE_PORT, (__u8)(UMPM_UART1_PORT + port_number), mask, @@ -351,92 +322,87 @@ static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask) } /** - * TIReadDownloadMemory - Read edgeport memory from TI chip + * read_download_mem - Read edgeport memory from TI chip * @dev: usb device pointer * @start_address: Device CPU address at which to read * @length: Length of above data * @address_type: Can read both XDATA and I2C * @buffer: pointer to input data buffer */ -static int TIReadDownloadMemory(struct usb_device *dev, int start_address, +static int read_download_mem(struct usb_device *dev, int start_address, int length, __u8 address_type, __u8 *buffer) { int status = 0; __u8 read_length; __be16 be_start_address; - - dbg ("%s - @ %x for %d", __func__, start_address, length); + + dbg("%s - @ %x for %d", __func__, start_address, length); /* Read in blocks of 64 bytes * (TI firmware can't handle more than 64 byte reads) */ while (length) { if (length > 64) - read_length= 64; + read_length = 64; else read_length = (__u8)length; if (read_length > 1) { - dbg ("%s - @ %x for %d", __func__, + dbg("%s - @ %x for %d", __func__, start_address, read_length); } - be_start_address = cpu_to_be16 (start_address); - status = TIReadVendorRequestSync (dev, - UMPC_MEMORY_READ, // Request - (__u16)address_type, // wValue (Address type) - (__force __u16)be_start_address, // wIndex (Address to read) - buffer, // TransferBuffer - read_length); // TransferBufferLength + be_start_address = cpu_to_be16(start_address); + status = ti_vread_sync(dev, UMPC_MEMORY_READ, + (__u16)address_type, + (__force __u16)be_start_address, + buffer, read_length); if (status) { - dbg ("%s - ERROR %x", __func__, status); + dbg("%s - ERROR %x", __func__, status); return status; } - if (read_length > 1) { + if (read_length > 1) usb_serial_debug_data(debug, &dev->dev, __func__, read_length, buffer); - } /* Update pointers/length */ start_address += read_length; buffer += read_length; length -= read_length; } - + return status; } -static int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer) +static int read_ram(struct usb_device *dev, int start_address, + int length, __u8 *buffer) { - return TIReadDownloadMemory (dev, - start_address, - length, - DTK_ADDR_SPACE_XDATA, - buffer); + return read_download_mem(dev, start_address, length, + DTK_ADDR_SPACE_XDATA, buffer); } /* Read edgeport memory to a given block */ -static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer) +static int read_boot_mem(struct edgeport_serial *serial, + int start_address, int length, __u8 *buffer) { int status = 0; int i; - for (i=0; i< length; i++) { - status = TIReadVendorRequestSync (serial->serial->dev, - UMPC_MEMORY_READ, // Request - serial->TI_I2C_Type, // wValue (Address type) - (__u16)(start_address+i), // wIndex - &buffer[i], // TransferBuffer - 0x01); // TransferBufferLength + for (i = 0; i < length; i++) { + status = ti_vread_sync(serial->serial->dev, + UMPC_MEMORY_READ, serial->TI_I2C_Type, + (__u16)(start_address+i), &buffer[i], 0x01); if (status) { - dbg ("%s - ERROR %x", __func__, status); + dbg("%s - ERROR %x", __func__, status); return status; } } - dbg ("%s - start_address = %x, length = %d", __func__, start_address, length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer); + dbg("%s - start_address = %x, length = %d", + __func__, start_address, length); + usb_serial_debug_data(debug, &serial->serial->dev->dev, + __func__, length, buffer); serial->TiReadI2C = 1; @@ -444,7 +410,8 @@ static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, } /* Write given block to TI EPROM memory */ -static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) +static int write_boot_mem(struct edgeport_serial *serial, + int start_address, int length, __u8 *buffer) { int status = 0; int i; @@ -452,57 +419,58 @@ static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, /* Must do a read before write */ if (!serial->TiReadI2C) { - status = TIReadBootMemory(serial, 0, 1, &temp); + status = read_boot_mem(serial, 0, 1, &temp); if (status) return status; } - for (i=0; i < length; ++i) { - status = TISendVendorRequestSync (serial->serial->dev, - UMPC_MEMORY_WRITE, // Request - buffer[i], // wValue - (__u16)(i+start_address), // wIndex - NULL, // TransferBuffer - 0); // TransferBufferLength + for (i = 0; i < length; ++i) { + status = ti_vsend_sync(serial->serial->dev, + UMPC_MEMORY_WRITE, buffer[i], + (__u16)(i + start_address), NULL, 0); if (status) return status; } - dbg ("%s - start_sddr = %x, length = %d", __func__, start_address, length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer); + dbg("%s - start_sddr = %x, length = %d", + __func__, start_address, length); + usb_serial_debug_data(debug, &serial->serial->dev->dev, + __func__, length, buffer); return status; } /* Write edgeport I2C memory to TI chip */ -static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer) +static int write_i2c_mem(struct edgeport_serial *serial, + int start_address, int length, __u8 address_type, __u8 *buffer) { int status = 0; int write_length; __be16 be_start_address; /* We can only send a maximum of 1 aligned byte page at a time */ - + /* calulate the number of bytes left in the first page */ - write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1)); + write_length = EPROM_PAGE_SIZE - + (start_address & (EPROM_PAGE_SIZE - 1)); if (write_length > length) write_length = length; - dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __func__, start_address, write_length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer); + dbg("%s - BytesInFirstPage Addr = %x, length = %d", + __func__, start_address, write_length); + usb_serial_debug_data(debug, &serial->serial->dev->dev, + __func__, write_length, buffer); /* Write first page */ - be_start_address = cpu_to_be16 (start_address); - status = TISendVendorRequestSync (serial->serial->dev, - UMPC_MEMORY_WRITE, // Request - (__u16)address_type, // wValue - (__force __u16)be_start_address, // wIndex - buffer, // TransferBuffer - write_length); + be_start_address = cpu_to_be16(start_address); + status = ti_vsend_sync(serial->serial->dev, + UMPC_MEMORY_WRITE, (__u16)address_type, + (__force __u16)be_start_address, + buffer, write_length); if (status) { - dbg ("%s - ERROR %d", __func__, status); + dbg("%s - ERROR %d", __func__, status); return status; } @@ -510,29 +478,31 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address start_address += write_length; buffer += write_length; - /* We should be aligned now -- can write max page size bytes at a time */ + /* We should be aligned now -- can write + max page size bytes at a time */ while (length) { if (length > EPROM_PAGE_SIZE) write_length = EPROM_PAGE_SIZE; else write_length = length; - dbg ("%s - Page Write Addr = %x, length = %d", __func__, start_address, write_length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer); + dbg("%s - Page Write Addr = %x, length = %d", + __func__, start_address, write_length); + usb_serial_debug_data(debug, &serial->serial->dev->dev, + __func__, write_length, buffer); /* Write next page */ - be_start_address = cpu_to_be16 (start_address); - status = TISendVendorRequestSync (serial->serial->dev, - UMPC_MEMORY_WRITE, // Request - (__u16)address_type, // wValue - (__force __u16)be_start_address, // wIndex - buffer, // TransferBuffer - write_length); // TransferBufferLength + be_start_address = cpu_to_be16(start_address); + status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, + (__u16)address_type, + (__force __u16)be_start_address, + buffer, write_length); if (status) { - dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __func__, status); + dev_err(&serial->serial->dev->dev, "%s - ERROR %d\n", + __func__, status); return status; } - + length -= write_length; start_address += write_length; buffer += write_length; @@ -541,25 +511,25 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address } /* Examine the UMP DMA registers and LSR - * + * * Check the MSBit of the X and Y DMA byte count registers. * A zero in this bit indicates that the TX DMA buffers are empty * then check the TX Empty bit in the UART. */ -static int TIIsTxActive (struct edgeport_port *port) +static int tx_active(struct edgeport_port *port) { int status; struct out_endpoint_desc_block *oedb; __u8 *lsr; int bytes_left = 0; - oedb = kmalloc (sizeof (* oedb), GFP_KERNEL); + oedb = kmalloc(sizeof(*oedb), GFP_KERNEL); if (!oedb) { - dev_err (&port->port->dev, "%s - out of memory\n", __func__); + dev_err(&port->port->dev, "%s - out of memory\n", __func__); return -ENOMEM; } - lsr = kmalloc (1, GFP_KERNEL); /* Sigh, that's right, just one byte, + lsr = kmalloc(1, GFP_KERNEL); /* Sigh, that's right, just one byte, as not all platforms can do DMA from stack */ if (!lsr) { @@ -567,51 +537,47 @@ static int TIIsTxActive (struct edgeport_port *port) return -ENOMEM; } /* Read the DMA Count Registers */ - status = TIReadRam (port->port->serial->dev, - port->dma_address, - sizeof( *oedb), - (void *)oedb); - + status = read_ram(port->port->serial->dev, port->dma_address, + sizeof(*oedb), (void *)oedb); if (status) goto exit_is_tx_active; - dbg ("%s - XByteCount 0x%X", __func__, oedb->XByteCount); + dbg("%s - XByteCount 0x%X", __func__, oedb->XByteCount); /* and the LSR */ - status = TIReadRam (port->port->serial->dev, - port->uart_base + UMPMEM_OFFS_UART_LSR, - 1, - lsr); + status = read_ram(port->port->serial->dev, + port->uart_base + UMPMEM_OFFS_UART_LSR, 1, lsr); if (status) goto exit_is_tx_active; - dbg ("%s - LSR = 0x%X", __func__, *lsr); - + dbg("%s - LSR = 0x%X", __func__, *lsr); + /* If either buffer has data or we are transmitting then return TRUE */ - if ((oedb->XByteCount & 0x80 ) != 0 ) + if ((oedb->XByteCount & 0x80) != 0) bytes_left += 64; - if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 ) + if ((*lsr & UMP_UART_LSR_TX_MASK) == 0) bytes_left += 1; /* We return Not Active if we get any kind of error */ exit_is_tx_active: - dbg ("%s - return %d", __func__, bytes_left ); + dbg("%s - return %d", __func__, bytes_left); kfree(lsr); kfree(oedb); return bytes_left; } -static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int flush) +static void chase_port(struct edgeport_port *port, unsigned long timeout, + int flush) { int baud_rate; - struct tty_struct *tty = port->port->tty; + struct tty_struct *tty = port->port->port.tty; wait_queue_t wait; unsigned long flags; if (!timeout) - timeout = (HZ*EDGE_CLOSING_WAIT)/100; + timeout = (HZ * EDGE_CLOSING_WAIT)/100; /* wait for data to drain from the buffer */ spin_lock_irqsave(&port->ep_lock, flags); @@ -621,7 +587,8 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f set_current_state(TASK_INTERRUPTIBLE); if (edge_buf_data_avail(port->ep_out_buf) == 0 || timeout == 0 || signal_pending(current) - || !usb_get_intfdata(port->port->serial->interface)) /* disconnect */ + || !usb_get_intfdata(port->port->serial->interface)) + /* disconnect */ break; spin_unlock_irqrestore(&port->ep_lock, flags); timeout = schedule_timeout(timeout); @@ -636,8 +603,9 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f /* wait for data to drain from the device */ timeout += jiffies; while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && usb_get_intfdata(port->port->serial->interface)) { /* not disconnected */ - if (!TIIsTxActive(port)) + && usb_get_intfdata(port->port->serial->interface)) { + /* not disconnected */ + if (!tx_active(port)) break; msleep(10); } @@ -647,72 +615,72 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f return; /* wait one more character time, based on baud rate */ - /* (TIIsTxActive doesn't seem to wait for the last byte) */ - if ((baud_rate=port->baud_rate) == 0) + /* (tx_active doesn't seem to wait for the last byte) */ + baud_rate = port->baud_rate; + if (baud_rate == 0) baud_rate = 50; msleep(max(1, DIV_ROUND_UP(10000, baud_rate))); } -static int TIChooseConfiguration (struct usb_device *dev) +static int choose_config(struct usb_device *dev) { - // There may be multiple configurations on this device, in which case - // we would need to read and parse all of them to find out which one - // we want. However, we just support one config at this point, - // configuration # 1, which is Config Descriptor 0. + /* + * There may be multiple configurations on this device, in which case + * we would need to read and parse all of them to find out which one + * we want. However, we just support one config at this point, + * configuration # 1, which is Config Descriptor 0. + */ - dbg ("%s - Number of Interfaces = %d", __func__, dev->config->desc.bNumInterfaces); - dbg ("%s - MAX Power = %d", __func__, dev->config->desc.bMaxPower*2); + dbg("%s - Number of Interfaces = %d", + __func__, dev->config->desc.bNumInterfaces); + dbg("%s - MAX Power = %d", + __func__, dev->config->desc.bMaxPower * 2); if (dev->config->desc.bNumInterfaces != 1) { - dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__); + dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", + __func__); return -ENODEV; } return 0; } -static int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) +static int read_rom(struct edgeport_serial *serial, + int start_address, int length, __u8 *buffer) { int status; if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { - status = TIReadDownloadMemory (serial->serial->dev, + status = read_download_mem(serial->serial->dev, start_address, length, serial->TI_I2C_Type, buffer); } else { - status = TIReadBootMemory (serial, - start_address, - length, - buffer); + status = read_boot_mem(serial, start_address, length, + buffer); } - return status; } -static int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) +static int write_rom(struct edgeport_serial *serial, int start_address, + int length, __u8 *buffer) { if (serial->product_info.TiMode == TI_MODE_BOOT) - return TIWriteBootMemory (serial, - start_address, - length, - buffer); + return write_boot_mem(serial, start_address, length, + buffer); if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) - return TIWriteDownloadI2C (serial, - start_address, - length, - serial->TI_I2C_Type, - buffer); - + return write_i2c_mem(serial, start_address, length, + serial->TI_I2C_Type, buffer); return -EINVAL; } /* Read a descriptor header from I2C based on type */ -static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc) +static int get_descriptor_addr(struct edgeport_serial *serial, + int desc_type, struct ti_i2c_desc *rom_desc) { int start_address; int status; @@ -720,41 +688,42 @@ static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type /* Search for requested descriptor in I2C */ start_address = 2; do { - status = TIReadRom (serial, + status = read_rom(serial, start_address, sizeof(struct ti_i2c_desc), - (__u8 *)rom_desc ); + (__u8 *)rom_desc); if (status) return 0; if (rom_desc->Type == desc_type) return start_address; - start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; + start_address = start_address + sizeof(struct ti_i2c_desc) + + rom_desc->Size; } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); - + return 0; } /* Validate descriptor checksum */ -static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer) +static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer) { __u16 i; __u8 cs = 0; - for (i=0; i < rom_desc->Size; i++) { + for (i = 0; i < rom_desc->Size; i++) cs = (__u8)(cs + buffer[i]); - } + if (cs != rom_desc->CheckSum) { - dbg ("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs); + dbg("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs); return -EINVAL; } return 0; } /* Make sure that the I2C image is good */ -static int TiValidateI2cImage (struct edgeport_serial *serial) +static int check_i2c_image(struct edgeport_serial *serial) { struct device *dev = &serial->serial->dev->dev; int status = 0; @@ -763,120 +732,124 @@ static int TiValidateI2cImage (struct edgeport_serial *serial) __u8 *buffer; __u16 ttype; - rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); + rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL); if (!rom_desc) { - dev_err (dev, "%s - out of memory\n", __func__); + dev_err(dev, "%s - out of memory\n", __func__); return -ENOMEM; } - buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL); + buffer = kmalloc(TI_MAX_I2C_SIZE, GFP_KERNEL); if (!buffer) { - dev_err (dev, "%s - out of memory when allocating buffer\n", __func__); - kfree (rom_desc); + dev_err(dev, "%s - out of memory when allocating buffer\n", + __func__); + kfree(rom_desc); return -ENOMEM; } - // Read the first byte (Signature0) must be 0x52 or 0x10 - status = TIReadRom (serial, 0, 1, buffer); + /* Read the first byte (Signature0) must be 0x52 or 0x10 */ + status = read_rom(serial, 0, 1, buffer); if (status) - goto ExitTiValidateI2cImage; + goto out; if (*buffer != UMP5152 && *buffer != UMP3410) { - dev_err (dev, "%s - invalid buffer signature\n", __func__); + dev_err(dev, "%s - invalid buffer signature\n", __func__); status = -ENODEV; - goto ExitTiValidateI2cImage; + goto out; } do { - // Validate the I2C - status = TIReadRom (serial, + /* Validate the I2C */ + status = read_rom(serial, start_address, sizeof(struct ti_i2c_desc), (__u8 *)rom_desc); if (status) break; - if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) { + if ((start_address + sizeof(struct ti_i2c_desc) + + rom_desc->Size) > TI_MAX_I2C_SIZE) { status = -ENODEV; - dbg ("%s - structure too big, erroring out.", __func__); + dbg("%s - structure too big, erroring out.", __func__); break; } - dbg ("%s Type = 0x%x", __func__, rom_desc->Type); + dbg("%s Type = 0x%x", __func__, rom_desc->Type); - // Skip type 2 record + /* Skip type 2 record */ ttype = rom_desc->Type & 0x0f; - if ( ttype != I2C_DESC_TYPE_FIRMWARE_BASIC - && ttype != I2C_DESC_TYPE_FIRMWARE_AUTO ) { - // Read the descriptor data - status = TIReadRom(serial, - start_address+sizeof(struct ti_i2c_desc), - rom_desc->Size, - buffer); + if (ttype != I2C_DESC_TYPE_FIRMWARE_BASIC + && ttype != I2C_DESC_TYPE_FIRMWARE_AUTO) { + /* Read the descriptor data */ + status = read_rom(serial, start_address + + sizeof(struct ti_i2c_desc), + rom_desc->Size, buffer); if (status) break; - status = ValidChecksum(rom_desc, buffer); + status = valid_csum(rom_desc, buffer); if (status) break; } - start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; + start_address = start_address + sizeof(struct ti_i2c_desc) + + rom_desc->Size; - } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE)); + } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && + (start_address < TI_MAX_I2C_SIZE)); - if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE)) + if ((rom_desc->Type != I2C_DESC_TYPE_ION) || + (start_address > TI_MAX_I2C_SIZE)) status = -ENODEV; -ExitTiValidateI2cImage: - kfree (buffer); - kfree (rom_desc); +out: + kfree(buffer); + kfree(rom_desc); return status; } -static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer) +static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer) { int status; int start_address; struct ti_i2c_desc *rom_desc; struct edge_ti_manuf_descriptor *desc; - rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); + rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL); if (!rom_desc) { - dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __func__); + dev_err(&serial->serial->dev->dev, "%s - out of memory\n", + __func__); return -ENOMEM; } - start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc); + start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_ION, + rom_desc); if (!start_address) { - dbg ("%s - Edge Descriptor not found in I2C", __func__); + dbg("%s - Edge Descriptor not found in I2C", __func__); status = -ENODEV; goto exit; } - // Read the descriptor data - status = TIReadRom (serial, - start_address+sizeof(struct ti_i2c_desc), - rom_desc->Size, - buffer); + /* Read the descriptor data */ + status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc), + rom_desc->Size, buffer); if (status) goto exit; - - status = ValidChecksum(rom_desc, buffer); - + + status = valid_csum(rom_desc, buffer); + desc = (struct edge_ti_manuf_descriptor *)buffer; - dbg ( "%s - IonConfig 0x%x", __func__, desc->IonConfig ); - dbg ( "%s - Version %d", __func__, desc->Version ); - dbg ( "%s - Cpu/Board 0x%x", __func__, desc->CpuRev_BoardRev ); - dbg ( "%s - NumPorts %d", __func__, desc->NumPorts ); - dbg ( "%s - NumVirtualPorts %d", __func__, desc->NumVirtualPorts ); - dbg ( "%s - TotalPorts %d", __func__, desc->TotalPorts ); + dbg("%s - IonConfig 0x%x", __func__, desc->IonConfig); + dbg("%s - Version %d", __func__, desc->Version); + dbg("%s - Cpu/Board 0x%x", __func__, desc->CpuRev_BoardRev); + dbg("%s - NumPorts %d", __func__, desc->NumPorts); + dbg("%s - NumVirtualPorts %d", __func__, desc->NumVirtualPorts); + dbg("%s - TotalPorts %d", __func__, desc->TotalPorts); exit: - kfree (rom_desc); + kfree(rom_desc); return status; } /* Build firmware header used for firmware update */ -static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev) +static int build_i2c_fw_hdr(__u8 *header, struct device *dev) { __u8 *buffer; int buffer_size; @@ -889,24 +862,28 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev) const struct firmware *fw; const char *fw_name = "edgeport/down3.bin"; - // In order to update the I2C firmware we must change the type 2 record to type 0xF2. - // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver - // will download the latest firmware (padded to 15.5k) into the UMP ram. - // And finally when the device comes back up in download mode the driver will cause - // the new firmware to be copied from the UMP Ram to I2C and the firmware will update - // the record type from 0xf2 to 0x02. - - // Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record) - buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec)); - - buffer = kmalloc (buffer_size, GFP_KERNEL); + /* In order to update the I2C firmware we must change the type 2 record + * to type 0xF2. This will force the UMP to come up in Boot Mode. + * Then while in boot mode, the driver will download the latest + * firmware (padded to 15.5k) into the UMP ram. And finally when the + * device comes back up in download mode the driver will cause the new + * firmware to be copied from the UMP Ram to I2C and the firmware will + * update the record type from 0xf2 to 0x02. + */ + + /* Allocate a 15.5k buffer + 2 bytes for version number + * (Firmware Record) */ + buffer_size = (((1024 * 16) - 512 ) + + sizeof(struct ti_i2c_firmware_rec)); + + buffer = kmalloc(buffer_size, GFP_KERNEL); if (!buffer) { - dev_err (dev, "%s - out of memory\n", __func__); + dev_err(dev, "%s - out of memory\n", __func__); return -ENOMEM; } - + // Set entire image of 0xffs - memset (buffer, 0xff, buffer_size); + memset(buffer, 0xff, buffer_size); err = request_firmware(&fw, fw_name, dev); if (err) { @@ -921,16 +898,16 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev) OperationalMinorVersion = fw->data[1]; OperationalBuildNumber = fw->data[2] | (fw->data[3] << 8); - // Copy version number into firmware record + /* Copy version number into firmware record */ firmware_rec = (struct ti_i2c_firmware_rec *)buffer; firmware_rec->Ver_Major = OperationalMajorVersion; firmware_rec->Ver_Minor = OperationalMinorVersion; - // Pointer to fw_down memory image + /* Pointer to fw_down memory image */ img_header = (struct ti_i2c_image_header *)&fw->data[4]; - memcpy (buffer + sizeof(struct ti_i2c_firmware_rec), + memcpy(buffer + sizeof(struct ti_i2c_firmware_rec), &fw->data[4 + sizeof(struct ti_i2c_image_header)], le16_to_cpu(img_header->Length)); @@ -940,12 +917,12 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev) cs = (__u8)(cs + buffer[i]); } - kfree (buffer); + kfree(buffer); - // Build new header + /* Build new header */ i2c_header = (struct ti_i2c_desc *)header; firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data; - + i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK; i2c_header->Size = (__u16)buffer_size; i2c_header->CheckSum = cs; @@ -956,103 +933,100 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev) } /* Try to figure out what type of I2c we have */ -static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial) +static int i2c_type_bootmode(struct edgeport_serial *serial) { int status; __u8 data; - - // Try to read type 2 - status = TIReadVendorRequestSync (serial->serial->dev, - UMPC_MEMORY_READ, // Request - DTK_ADDR_SPACE_I2C_TYPE_II, // wValue (Address type) - 0, // wIndex - &data, // TransferBuffer - 0x01); // TransferBufferLength + + /* Try to read type 2 */ + status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ, + DTK_ADDR_SPACE_I2C_TYPE_II, 0, &data, 0x01); if (status) - dbg ("%s - read 2 status error = %d", __func__, status); + dbg("%s - read 2 status error = %d", __func__, status); else - dbg ("%s - read 2 data = 0x%x", __func__, data); + dbg("%s - read 2 data = 0x%x", __func__, data); if ((!status) && (data == UMP5152 || data == UMP3410)) { - dbg ("%s - ROM_TYPE_II", __func__); + dbg("%s - ROM_TYPE_II", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; return 0; } - // Try to read type 3 - status = TIReadVendorRequestSync (serial->serial->dev, - UMPC_MEMORY_READ, // Request - DTK_ADDR_SPACE_I2C_TYPE_III, // wValue (Address type) - 0, // wIndex - &data, // TransferBuffer - 0x01); // TransferBufferLength + /* Try to read type 3 */ + status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ, + DTK_ADDR_SPACE_I2C_TYPE_III, 0, &data, 0x01); if (status) - dbg ("%s - read 3 status error = %d", __func__, status); + dbg("%s - read 3 status error = %d", __func__, status); else - dbg ("%s - read 2 data = 0x%x", __func__, data); + dbg("%s - read 2 data = 0x%x", __func__, data); if ((!status) && (data == UMP5152 || data == UMP3410)) { - dbg ("%s - ROM_TYPE_III", __func__); + dbg("%s - ROM_TYPE_III", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III; return 0; } - dbg ("%s - Unknown", __func__); + dbg("%s - Unknown", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; return -ENODEV; } -static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int length, int *num_sent) +static int bulk_xfer(struct usb_serial *serial, void *buffer, + int length, int *num_sent) { int status; - status = usb_bulk_msg (serial->dev, - usb_sndbulkpipe(serial->dev, - serial->port[0]->bulk_out_endpointAddress), - buffer, - length, - num_sent, - 1000); + status = usb_bulk_msg(serial->dev, + usb_sndbulkpipe(serial->dev, + serial->port[0]->bulk_out_endpointAddress), + buffer, length, num_sent, 1000); return status; } /* Download given firmware image to the device (IN BOOT MODE) */ -static int TIDownloadCodeImage (struct edgeport_serial *serial, __u8 *image, int image_length) +static int download_code(struct edgeport_serial *serial, __u8 *image, + int image_length) { int status = 0; int pos; int transfer; int done; - // Transfer firmware image + /* Transfer firmware image */ for (pos = 0; pos < image_length; ) { - // Read the next buffer from file + /* Read the next buffer from file */ transfer = image_length - pos; if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE) transfer = EDGE_FW_BULK_MAX_PACKET_SIZE; - // Transfer data - status = TISendBulkTransferSync (serial->serial, &image[pos], transfer, &done); + /* Transfer data */ + status = bulk_xfer(serial->serial, &image[pos], + transfer, &done); if (status) break; - // Advance buffer pointer + /* Advance buffer pointer */ pos += done; } return status; } -// FIXME!!! -static int TIConfigureBootDevice (struct usb_device *dev) +/* FIXME!!! */ +static int config_boot_dev(struct usb_device *dev) { return 0; } +static int ti_cpu_rev(struct edge_ti_manuf_descriptor *desc) +{ + return TI_GET_CPU_REVISION(desc->CpuRev_BoardRev); +} + /** * DownloadTIFirmware - Download run-time operating firmware to the TI5052 - * + * * This routine downloads the main operating code into the TI5052, using the * boot code already burned into E2PROM or ROM. */ -static int TIDownloadFirmware (struct edgeport_serial *serial) +static int download_fw(struct edgeport_serial *serial) { struct device *dev = &serial->serial->dev->dev; int status = 0; @@ -1071,22 +1045,25 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) /* Default to type 2 i2c */ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; - status = TIChooseConfiguration (serial->serial->dev); + status = choose_config(serial->serial->dev); if (status) return status; interface = &serial->serial->interface->cur_altsetting->desc; if (!interface) { - dev_err (dev, "%s - no interface set, error!\n", __func__); + dev_err(dev, "%s - no interface set, error!\n", __func__); return -ENODEV; } - // Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING - // if we have more than one endpoint we are definitely in download mode + /* + * Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING + * if we have more than one endpoint we are definitely in download + * mode + */ if (interface->bNumEndpoints > 1) serial->product_info.TiMode = TI_MODE_DOWNLOAD; else - // Otherwise we will remain in configuring mode + /* Otherwise we will remain in configuring mode */ serial->product_info.TiMode = TI_MODE_CONFIGURING; /********************************************************************/ @@ -1097,256 +1074,273 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) dbg("%s - RUNNING IN DOWNLOAD MODE", __func__); - status = TiValidateI2cImage (serial); + status = check_i2c_image(serial); if (status) { dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__); return status; } - + /* Validate Hardware version number * Read Manufacturing Descriptor from TI Based Edgeport */ - ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); + ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL); if (!ti_manuf_desc) { - dev_err (dev, "%s - out of memory.\n", __func__); + dev_err(dev, "%s - out of memory.\n", __func__); return -ENOMEM; } - status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); + status = get_manuf_info(serial, (__u8 *)ti_manuf_desc); if (status) { - kfree (ti_manuf_desc); + kfree(ti_manuf_desc); return status; } - // Check version number of ION descriptor - if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) { - dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __func__, - TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev)); - kfree (ti_manuf_desc); - return -EINVAL; - } + /* Check version number of ION descriptor */ + if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) { + dbg("%s - Wrong CPU Rev %d (Must be 2)", + __func__, ti_cpu_rev(ti_manuf_desc)); + kfree(ti_manuf_desc); + return -EINVAL; + } - rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); + rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL); if (!rom_desc) { - dev_err (dev, "%s - out of memory.\n", __func__); - kfree (ti_manuf_desc); + dev_err(dev, "%s - out of memory.\n", __func__); + kfree(ti_manuf_desc); return -ENOMEM; } - // Search for type 2 record (firmware record) - if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) { + /* Search for type 2 record (firmware record) */ + start_address = get_descriptor_addr(serial, + I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc); + if (start_address != 0) { struct ti_i2c_firmware_rec *firmware_version; __u8 record; - dbg ("%s - Found Type FIRMWARE (Type 2) record", __func__); + dbg("%s - Found Type FIRMWARE (Type 2) record", + __func__); - firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL); + firmware_version = kmalloc(sizeof(*firmware_version), + GFP_KERNEL); if (!firmware_version) { - dev_err (dev, "%s - out of memory.\n", __func__); - kfree (rom_desc); - kfree (ti_manuf_desc); + dev_err(dev, "%s - out of memory.\n", __func__); + kfree(rom_desc); + kfree(ti_manuf_desc); return -ENOMEM; } - // Validate version number - // Read the descriptor data - status = TIReadRom (serial, - start_address+sizeof(struct ti_i2c_desc), + /* Validate version number + * Read the descriptor data + */ + status = read_rom(serial, start_address + + sizeof(struct ti_i2c_desc), sizeof(struct ti_i2c_firmware_rec), (__u8 *)firmware_version); if (status) { - kfree (firmware_version); - kfree (rom_desc); - kfree (ti_manuf_desc); + kfree(firmware_version); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } - // Check version number of download with current version in I2c - download_cur_ver = (firmware_version->Ver_Major << 8) + + /* Check version number of download with current + version in I2c */ + download_cur_ver = (firmware_version->Ver_Major << 8) + (firmware_version->Ver_Minor); download_new_ver = (OperationalMajorVersion << 8) + (OperationalMinorVersion); - dbg ("%s - >>>Firmware Versions Device %d.%d Driver %d.%d", - __func__, - firmware_version->Ver_Major, - firmware_version->Ver_Minor, - OperationalMajorVersion, - OperationalMinorVersion); + dbg("%s - >> FW Versions Device %d.%d Driver %d.%d", + __func__, + firmware_version->Ver_Major, + firmware_version->Ver_Minor, + OperationalMajorVersion, + OperationalMinorVersion); - // Check if we have an old version in the I2C and update if necessary + /* Check if we have an old version in the I2C and + update if necessary */ if (download_cur_ver != download_new_ver) { - dbg ("%s - Update I2C Download from %d.%d to %d.%d", - __func__, - firmware_version->Ver_Major, - firmware_version->Ver_Minor, - OperationalMajorVersion, - OperationalMinorVersion); - - // In order to update the I2C firmware we must change the type 2 record to type 0xF2. - // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver - // will download the latest firmware (padded to 15.5k) into the UMP ram. - // And finally when the device comes back up in download mode the driver will cause - // the new firmware to be copied from the UMP Ram to I2C and the firmware will update - // the record type from 0xf2 to 0x02. - + dbg("%s - Update I2C dld from %d.%d to %d.%d", + __func__, + firmware_version->Ver_Major, + firmware_version->Ver_Minor, + OperationalMajorVersion, + OperationalMinorVersion); + + /* In order to update the I2C firmware we must + * change the type 2 record to type 0xF2. This + * will force the UMP to come up in Boot Mode. + * Then while in boot mode, the driver will + * download the latest firmware (padded to + * 15.5k) into the UMP ram. Finally when the + * device comes back up in download mode the + * driver will cause the new firmware to be + * copied from the UMP Ram to I2C and the + * firmware will update the record type from + * 0xf2 to 0x02. + */ record = I2C_DESC_TYPE_FIRMWARE_BLANK; - // Change the I2C Firmware record type to 0xf2 to trigger an update - status = TIWriteRom (serial, - start_address, - sizeof(record), - &record); + /* Change the I2C Firmware record type to + 0xf2 to trigger an update */ + status = write_rom(serial, start_address, + sizeof(record), &record); if (status) { - kfree (firmware_version); - kfree (rom_desc); - kfree (ti_manuf_desc); + kfree(firmware_version); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } - // verify the write -- must do this in order for write to - // complete before we do the hardware reset - status = TIReadRom (serial, + /* verify the write -- must do this in order + * for write to complete before we do the + * hardware reset + */ + status = read_rom(serial, start_address, sizeof(record), &record); - if (status) { - kfree (firmware_version); - kfree (rom_desc); - kfree (ti_manuf_desc); + kfree(firmware_version); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) { - dev_err (dev, "%s - error resetting device\n", __func__); - kfree (firmware_version); - kfree (rom_desc); - kfree (ti_manuf_desc); + dev_err(dev, + "%s - error resetting device\n", + __func__); + kfree(firmware_version); + kfree(rom_desc); + kfree(ti_manuf_desc); return -ENODEV; } - dbg ("%s - HARDWARE RESET", __func__); + dbg("%s - HARDWARE RESET", __func__); - // Reset UMP -- Back to BOOT MODE - status = TISendVendorRequestSync (serial->serial->dev, - UMPC_HARDWARE_RESET, // Request - 0, // wValue - 0, // wIndex - NULL, // TransferBuffer - 0); // TransferBufferLength + /* Reset UMP -- Back to BOOT MODE */ + status = ti_vsend_sync(serial->serial->dev, + UMPC_HARDWARE_RESET, + 0, 0, NULL, 0); - dbg ( "%s - HARDWARE RESET return %d", __func__, status); + dbg("%s - HARDWARE RESET return %d", + __func__, status); /* return an error on purpose. */ - kfree (firmware_version); - kfree (rom_desc); - kfree (ti_manuf_desc); + kfree(firmware_version); + kfree(rom_desc); + kfree(ti_manuf_desc); return -ENODEV; } - kfree (firmware_version); + kfree(firmware_version); } - // Search for type 0xF2 record (firmware blank record) - else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { - #define HEADER_SIZE (sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec)) + /* Search for type 0xF2 record (firmware blank record) */ + else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { +#define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \ + sizeof(struct ti_i2c_firmware_rec)) __u8 *header; __u8 *vheader; - header = kmalloc (HEADER_SIZE, GFP_KERNEL); + header = kmalloc(HEADER_SIZE, GFP_KERNEL); if (!header) { - dev_err (dev, "%s - out of memory.\n", __func__); - kfree (rom_desc); - kfree (ti_manuf_desc); + dev_err(dev, "%s - out of memory.\n", __func__); + kfree(rom_desc); + kfree(ti_manuf_desc); return -ENOMEM; } - - vheader = kmalloc (HEADER_SIZE, GFP_KERNEL); + + vheader = kmalloc(HEADER_SIZE, GFP_KERNEL); if (!vheader) { - dev_err (dev, "%s - out of memory.\n", __func__); - kfree (header); - kfree (rom_desc); - kfree (ti_manuf_desc); + dev_err(dev, "%s - out of memory.\n", __func__); + kfree(header); + kfree(rom_desc); + kfree(ti_manuf_desc); return -ENOMEM; } - - dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __func__); - - // In order to update the I2C firmware we must change the type 2 record to type 0xF2. - // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver - // will download the latest firmware (padded to 15.5k) into the UMP ram. - // And finally when the device comes back up in download mode the driver will cause - // the new firmware to be copied from the UMP Ram to I2C and the firmware will update - // the record type from 0xf2 to 0x02. - status = BuildI2CFirmwareHeader(header, dev); + + dbg("%s - Found Type BLANK FIRMWARE (Type F2) record", + __func__); + + /* + * In order to update the I2C firmware we must change + * the type 2 record to type 0xF2. This will force the + * UMP to come up in Boot Mode. Then while in boot + * mode, the driver will download the latest firmware + * (padded to 15.5k) into the UMP ram. Finally when the + * device comes back up in download mode the driver + * will cause the new firmware to be copied from the + * UMP Ram to I2C and the firmware will update the + * record type from 0xf2 to 0x02. + */ + status = build_i2c_fw_hdr(header, dev); if (status) { - kfree (vheader); - kfree (header); - kfree (rom_desc); - kfree (ti_manuf_desc); + kfree(vheader); + kfree(header); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } - // Update I2C with type 0xf2 record with correct size and checksum - status = TIWriteRom (serial, + /* Update I2C with type 0xf2 record with correct + size and checksum */ + status = write_rom(serial, start_address, HEADER_SIZE, header); if (status) { - kfree (vheader); - kfree (header); - kfree (rom_desc); - kfree (ti_manuf_desc); + kfree(vheader); + kfree(header); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } - // verify the write -- must do this in order for write to - // complete before we do the hardware reset - status = TIReadRom (serial, - start_address, - HEADER_SIZE, - vheader); + /* verify the write -- must do this in order for + write to complete before we do the hardware reset */ + status = read_rom(serial, start_address, + HEADER_SIZE, vheader); if (status) { - dbg ("%s - can't read header back", __func__); - kfree (vheader); - kfree (header); - kfree (rom_desc); - kfree (ti_manuf_desc); + dbg("%s - can't read header back", __func__); + kfree(vheader); + kfree(header); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } if (memcmp(vheader, header, HEADER_SIZE)) { - dbg ("%s - write download record failed", __func__); - kfree (vheader); - kfree (header); - kfree (rom_desc); - kfree (ti_manuf_desc); + dbg("%s - write download record failed", + __func__); + kfree(vheader); + kfree(header); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } - kfree (vheader); - kfree (header); + kfree(vheader); + kfree(header); - dbg ("%s - Start firmware update", __func__); + dbg("%s - Start firmware update", __func__); - // Tell firmware to copy download image into I2C - status = TISendVendorRequestSync (serial->serial->dev, - UMPC_COPY_DNLD_TO_I2C, // Request - 0, // wValue - 0, // wIndex - NULL, // TransferBuffer - 0); // TransferBufferLength + /* Tell firmware to copy download image into I2C */ + status = ti_vsend_sync(serial->serial->dev, + UMPC_COPY_DNLD_TO_I2C, 0, 0, NULL, 0); - dbg ("%s - Update complete 0x%x", __func__, status); + dbg("%s - Update complete 0x%x", __func__, status); if (status) { - dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__); - kfree (rom_desc); - kfree (ti_manuf_desc); + dev_err(dev, + "%s - UMPC_COPY_DNLD_TO_I2C failed\n", + __func__); + kfree(rom_desc); + kfree(ti_manuf_desc); return status; } } // The device is running the download code - kfree (rom_desc); - kfree (ti_manuf_desc); + kfree(rom_desc); + kfree(ti_manuf_desc); return 0; } @@ -1355,32 +1349,26 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) /********************************************************************/ dbg("%s - RUNNING IN BOOT MODE", __func__); - // Configure the TI device so we can use the BULK pipes for download - status = TIConfigureBootDevice (serial->serial->dev); + /* Configure the TI device so we can use the BULK pipes for download */ + status = config_boot_dev(serial->serial->dev); if (status) return status; - if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) { - dbg ("%s - VID = 0x%x", __func__, + if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) + != USB_VENDOR_ID_ION) { + dbg("%s - VID = 0x%x", __func__, le16_to_cpu(serial->serial->dev->descriptor.idVendor)); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; - goto StayInBootMode; + goto stayinbootmode; } - // We have an ION device (I2c Must be programmed) - // Determine I2C image type - if (TIGetI2cTypeInBootMode(serial)) { - goto StayInBootMode; - } + /* We have an ION device (I2c Must be programmed) + Determine I2C image type */ + if (i2c_type_bootmode(serial)) + goto stayinbootmode; - // Registry variable set? - if (TIStayInBootMode) { - dbg ("%s - TIStayInBootMode", __func__); - goto StayInBootMode; - } - - // Check for ION Vendor ID and that the I2C is valid - if (!TiValidateI2cImage(serial)) { + /* Check for ION Vendor ID and that the I2C is valid */ + if (!check_i2c_image(serial)) { struct ti_i2c_image_header *header; int i; __u8 cs = 0; @@ -1393,49 +1381,52 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) /* Validate Hardware version number * Read Manufacturing Descriptor from TI Based Edgeport */ - ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); + ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL); if (!ti_manuf_desc) { - dev_err (dev, "%s - out of memory.\n", __func__); + dev_err(dev, "%s - out of memory.\n", __func__); return -ENOMEM; } - status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); + status = get_manuf_info(serial, (__u8 *)ti_manuf_desc); if (status) { - kfree (ti_manuf_desc); - goto StayInBootMode; + kfree(ti_manuf_desc); + goto stayinbootmode; } - // Check for version 2 - if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) { - dbg ("%s - Wrong CPU Rev %d (Must be 2)", __func__, - TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev)); - kfree (ti_manuf_desc); - goto StayInBootMode; + /* Check for version 2 */ + if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) { + dbg("%s - Wrong CPU Rev %d (Must be 2)", + __func__, ti_cpu_rev(ti_manuf_desc)); + kfree(ti_manuf_desc); + goto stayinbootmode; } - kfree (ti_manuf_desc); + kfree(ti_manuf_desc); - // In order to update the I2C firmware we must change the type 2 record to type 0xF2. - // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver - // will download the latest firmware (padded to 15.5k) into the UMP ram. - // And finally when the device comes back up in download mode the driver will cause - // the new firmware to be copied from the UMP Ram to I2C and the firmware will update - // the record type from 0xf2 to 0x02. - /* + * In order to update the I2C firmware we must change the type + * 2 record to type 0xF2. This will force the UMP to come up + * in Boot Mode. Then while in boot mode, the driver will + * download the latest firmware (padded to 15.5k) into the + * UMP ram. Finally when the device comes back up in download + * mode the driver will cause the new firmware to be copied + * from the UMP Ram to I2C and the firmware will update the + * record type from 0xf2 to 0x02. + * * Do we really have to copy the whole firmware image, * or could we do this in place! */ - // Allocate a 15.5k buffer + 3 byte header - buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header)); - buffer = kmalloc (buffer_size, GFP_KERNEL); + /* Allocate a 15.5k buffer + 3 byte header */ + buffer_size = (((1024 * 16) - 512) + + sizeof(struct ti_i2c_image_header)); + buffer = kmalloc(buffer_size, GFP_KERNEL); if (!buffer) { - dev_err (dev, "%s - out of memory\n", __func__); + dev_err(dev, "%s - out of memory\n", __func__); return -ENOMEM; } - - // Initialize the buffer to 0xff (pad the buffer) - memset (buffer, 0xff, buffer_size); + + /* Initialize the buffer to 0xff (pad the buffer) */ + memset(buffer, 0xff, buffer_size); err = request_firmware(&fw, fw_name, dev); if (err) { @@ -1447,38 +1438,43 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) memcpy(buffer, &fw->data[4], fw->size - 4); release_firmware(fw); - for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) { + for (i = sizeof(struct ti_i2c_image_header); + i < buffer_size; i++) { cs = (__u8)(cs + buffer[i]); } - + header = (struct ti_i2c_image_header *)buffer; - - // update length and checksum after padding - header->Length = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_i2c_image_header))); + + /* update length and checksum after padding */ + header->Length = cpu_to_le16((__u16)(buffer_size - + sizeof(struct ti_i2c_image_header))); header->CheckSum = cs; - // Download the operational code - dbg ("%s - Downloading operational code image (TI UMP)", __func__); - status = TIDownloadCodeImage (serial, buffer, buffer_size); + /* Download the operational code */ + dbg("%s - Downloading operational code image (TI UMP)", + __func__); + status = download_code(serial, buffer, buffer_size); - kfree (buffer); + kfree(buffer); if (status) { - dbg ("%s - Error downloading operational code image", __func__); + dbg("%s - Error downloading operational code image", + __func__); return status; } - // Device will reboot + /* Device will reboot */ serial->product_info.TiMode = TI_MODE_TRANSITIONING; - dbg ("%s - Download successful -- Device rebooting...", __func__); + dbg("%s - Download successful -- Device rebooting...", + __func__); /* return an error on purpose */ return -ENODEV; } -StayInBootMode: - // Eprom is invalid or blank stay in boot mode +stayinbootmode: + /* Eprom is invalid or blank stay in boot mode */ dbg("%s - STAYING IN BOOT MODE", __func__); serial->product_info.TiMode = TI_MODE_BOOT; @@ -1486,156 +1482,33 @@ StayInBootMode: } -static int TISetDtr (struct edgeport_port *port) -{ - int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - port->shadow_mcr |= MCR_DTR; - - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_DTR, - (__u8)(UMPM_UART1_PORT + port_number), - 1, /* set */ - NULL, - 0); -} - -static int TIClearDtr (struct edgeport_port *port) -{ - int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - port->shadow_mcr &= ~MCR_DTR; - - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_DTR, - (__u8)(UMPM_UART1_PORT + port_number), - 0, /* clear */ - NULL, - 0); -} - -static int TISetRts (struct edgeport_port *port) -{ - int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - port->shadow_mcr |= MCR_RTS; - - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_RTS, - (__u8)(UMPM_UART1_PORT + port_number), - 1, /* set */ - NULL, - 0); -} - -static int TIClearRts (struct edgeport_port *port) -{ - int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - port->shadow_mcr &= ~MCR_RTS; - - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_RTS, - (__u8)(UMPM_UART1_PORT + port_number), - 0, /* clear */ - NULL, - 0); -} - -static int TISetLoopBack (struct edgeport_port *port) -{ - int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_LOOPBACK, - (__u8)(UMPM_UART1_PORT + port_number), - 1, /* set */ - NULL, - 0); -} - -static int TIClearLoopBack (struct edgeport_port *port) -{ - int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_LOOPBACK, - (__u8)(UMPM_UART1_PORT + port_number), - 0, /* clear */ - NULL, - 0); -} - -static int TISetBreak (struct edgeport_port *port) +static int ti_do_config(struct edgeport_port *port, int feature, int on) { int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_BREAK, - (__u8)(UMPM_UART1_PORT + port_number), - 1, /* set */ - NULL, - 0); + on = !!on; /* 1 or 0 not bitmask */ + return send_cmd(port->port->serial->dev, + feature, (__u8)(UMPM_UART1_PORT + port_number), + on, NULL, 0); } -static int TIClearBreak (struct edgeport_port *port) -{ - int port_number = port->port->number - port->port->serial->minor; - - dbg ("%s", __func__); - return TIWriteCommandSync (port->port->serial->dev, - UMPC_SET_CLR_BREAK, - (__u8)(UMPM_UART1_PORT + port_number), - 0, /* clear */ - NULL, - 0); -} - -static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr) +static int restore_mcr(struct edgeport_port *port, __u8 mcr) { int status = 0; - dbg ("%s - %x", __func__, mcr); - - if (mcr & MCR_DTR) - status = TISetDtr (port); - else - status = TIClearDtr (port); + dbg("%s - %x", __func__, mcr); + status = ti_do_config(port, UMPC_SET_CLR_DTR, mcr & MCR_DTR); if (status) return status; - - if (mcr & MCR_RTS) - status = TISetRts (port); - else - status = TIClearRts (port); - + status = ti_do_config(port, UMPC_SET_CLR_RTS, mcr & MCR_RTS); if (status) return status; - - if (mcr & MCR_LOOPBACK) - status = TISetLoopBack (port); - else - status = TIClearLoopBack (port); - - return status; + return ti_do_config(port, UMPC_SET_CLR_LOOPBACK, mcr & MCR_LOOPBACK); } - - /* Convert TI LSR to standard UART flags */ -static __u8 MapLineStatus (__u8 ti_lsr) +static __u8 map_line_status(__u8 ti_lsr) { __u8 lsr = 0; @@ -1647,22 +1520,23 @@ static __u8 MapLineStatus (__u8 ti_lsr) MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR) /* parity error */ MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR) /* framing error */ MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK) /* break detected */ - MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* receive data available */ - MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* transmit holding register empty */ + MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* rx data available */ + MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* tx hold reg empty */ #undef MAP_FLAG return lsr; } -static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr) +static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) { struct async_icount *icount; struct tty_struct *tty; - dbg ("%s - %02x", __func__, msr); + dbg("%s - %02x", __func__, msr); - if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { + if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | + EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { icount = &edge_port->icount; /* update input line counters */ @@ -1674,13 +1548,13 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr) icount->dcd++; if (msr & EDGEPORT_MSR_DELTA_RI) icount->rng++; - wake_up_interruptible (&edge_port->delta_msr_wait); + wake_up_interruptible(&edge_port->delta_msr_wait); } /* Save the new modem status */ edge_port->shadow_msr = msr & 0xf0; - tty = edge_port->port->tty; + tty = edge_port->port->port.tty; /* handle CTS flow control */ if (tty && C_CRTSCTS(tty)) { if (msr & EDGEPORT_MSR_CTS) { @@ -1694,26 +1568,27 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr) return; } -static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data) +static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, + __u8 lsr, __u8 data) { struct async_icount *icount; - __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); + __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | + LSR_FRM_ERR | LSR_BREAK)); - dbg ("%s - %02x", __func__, new_lsr); + dbg("%s - %02x", __func__, new_lsr); edge_port->shadow_lsr = lsr; - if (new_lsr & LSR_BREAK) { + if (new_lsr & LSR_BREAK) /* * Parity and Framing errors only count if they * occur exclusive of a break being received. */ new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); - } /* Place LSR data byte into Rx buffer */ - if (lsr_data && edge_port->port->tty) - edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1); + if (lsr_data && edge_port->port->port.tty) + edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1); /* update input line counters */ icount = &edge_port->icount; @@ -1728,7 +1603,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 } -static void edge_interrupt_callback (struct urb *urb) +static void edge_interrupt_callback(struct urb *urb) { struct edgeport_serial *edge_serial = urb->context; struct usb_serial_port *port; @@ -1762,66 +1637,71 @@ static void edge_interrupt_callback (struct urb *urb) } if (!length) { - dbg ("%s - no data in urb", __func__); + dbg("%s - no data in urb", __func__); goto exit; } - - usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data); - + + usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, + __func__, length, data); + if (length != 2) { - dbg ("%s - expecting packet of size 2, got %d", __func__, length); + dbg("%s - expecting packet of size 2, got %d", + __func__, length); goto exit; } - port_number = TIUMP_GET_PORT_FROM_CODE (data[0]); - function = TIUMP_GET_FUNC_FROM_CODE (data[0]); - dbg ("%s - port_number %d, function %d, info 0x%x", + port_number = TIUMP_GET_PORT_FROM_CODE(data[0]); + function = TIUMP_GET_FUNC_FROM_CODE(data[0]); + dbg("%s - port_number %d, function %d, info 0x%x", __func__, port_number, function, data[1]); port = edge_serial->serial->port[port_number]; edge_port = usb_get_serial_port_data(port); if (!edge_port) { - dbg ("%s - edge_port not found", __func__); + dbg("%s - edge_port not found", __func__); return; } switch (function) { case TIUMP_INTERRUPT_CODE_LSR: - lsr = MapLineStatus(data[1]); + lsr = map_line_status(data[1]); if (lsr & UMP_UART_LSR_DATA_MASK) { - /* Save the LSR event for bulk read completion routine */ - dbg ("%s - LSR Event Port %u LSR Status = %02x", + /* Save the LSR event for bulk read + completion routine */ + dbg("%s - LSR Event Port %u LSR Status = %02x", __func__, port_number, lsr); edge_port->lsr_event = 1; edge_port->lsr_mask = lsr; } else { - dbg ("%s - ===== Port %d LSR Status = %02x ======", + dbg("%s - ===== Port %d LSR Status = %02x ======", __func__, port_number, lsr); - handle_new_lsr (edge_port, 0, lsr, 0); + handle_new_lsr(edge_port, 0, lsr, 0); } break; - case TIUMP_INTERRUPT_CODE_MSR: // MSR + case TIUMP_INTERRUPT_CODE_MSR: /* MSR */ /* Copy MSR from UMP */ msr = data[1]; - dbg ("%s - ===== Port %u MSR Status = %02x ======\n", + dbg("%s - ===== Port %u MSR Status = %02x ======\n", __func__, port_number, msr); - handle_new_msr (edge_port, msr); + handle_new_msr(edge_port, msr); break; default: - dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n", - __func__, data[1]); + dev_err(&urb->dev->dev, + "%s - Unknown Interrupt code from UMP %x\n", + __func__, data[1]); break; - + } exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", + dev_err(&urb->dev->dev, + "%s - usb_submit_urb failed with result %d\n", __func__, retval); } -static void edge_bulk_in_callback (struct urb *urb) +static void edge_bulk_in_callback(struct urb *urb) { struct edgeport_port *edge_port = urb->context; unsigned char *data = urb->transfer_buffer; @@ -1844,15 +1724,16 @@ static void edge_bulk_in_callback (struct urb *urb) __func__, status); return; default: - dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n", - __func__, status); + dev_err(&urb->dev->dev, + "%s - nonzero read bulk status received: %d\n", + __func__, status); } if (status == -EPIPE) goto exit; if (status) { - dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__); + dev_err(&urb->dev->dev, "%s - stopping read!\n", __func__); return; } @@ -1860,23 +1741,24 @@ static void edge_bulk_in_callback (struct urb *urb) if (edge_port->lsr_event) { edge_port->lsr_event = 0; - dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======", + dbg("%s ===== Port %u LSR Status = %02x, Data = %02x ======", __func__, port_number, edge_port->lsr_mask, *data); - handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data); + handle_new_lsr(edge_port, 1, edge_port->lsr_mask, *data); /* Adjust buffer length/pointer */ --urb->actual_length; ++data; } - tty = edge_port->port->tty; + tty = edge_port->port->port.tty; if (tty && urb->actual_length) { - usb_serial_debug_data(debug, &edge_port->port->dev, __func__, urb->actual_length, data); - - if (edge_port->close_pending) { - dbg ("%s - close is pending, dropping data on the floor.", __func__); - } else { - edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length); - } + usb_serial_debug_data(debug, &edge_port->port->dev, + __func__, urb->actual_length, data); + if (edge_port->close_pending) + dbg("%s - close pending, dropping data on the floor", + __func__); + else + edge_tty_recv(&edge_port->port->dev, tty, data, + urb->actual_length); edge_port->icount.rx += urb->actual_length; } @@ -1891,37 +1773,31 @@ exit: } spin_unlock(&edge_port->ep_lock); if (retval) - dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", + dev_err(&urb->dev->dev, + "%s - usb_submit_urb failed with result %d\n", __func__, retval); } -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) +static void edge_tty_recv(struct device *dev, struct tty_struct *tty, + unsigned char *data, int length) { - int cnt; - - do { - cnt = tty_buffer_request_room(tty, length); - if (cnt < length) { - dev_err(dev, "%s - dropping data, %d bytes lost\n", - __func__, length - cnt); - if(cnt == 0) - break; - } - tty_insert_flip_string(tty, data, cnt); - data += cnt; - length -= cnt; - } while (length > 0); + int queued; + tty_buffer_request_room(tty, length); + queued = tty_insert_flip_string(tty, data, length); + if (queued < length) + dev_err(dev, "%s - dropping data, %d bytes lost\n", + __func__, length - queued); tty_flip_buffer_push(tty); } -static void edge_bulk_out_callback (struct urb *urb) +static void edge_bulk_out_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status = urb->status; - dbg ("%s - port %d", __func__, port->number); + dbg("%s - port %d", __func__, port->number); edge_port->ep_write_urb_in_use = 0; @@ -1942,10 +1818,11 @@ static void edge_bulk_out_callback (struct urb *urb) } /* send any buffered data */ - edge_send(port); + edge_send(port->port.tty); } -static int edge_open (struct usb_serial_port *port, struct file * filp) +static int edge_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct edgeport_serial *edge_serial; @@ -1961,122 +1838,125 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) if (edge_port == NULL) return -ENODEV; - port->tty->low_latency = low_latency; + if (tty) + tty->low_latency = low_latency; port_number = port->number - port->serial->minor; switch (port_number) { - case 0: - edge_port->uart_base = UMPMEM_BASE_UART1; - edge_port->dma_address = UMPD_OEDB1_ADDRESS; - break; - case 1: - edge_port->uart_base = UMPMEM_BASE_UART2; - edge_port->dma_address = UMPD_OEDB2_ADDRESS; - break; - default: - dev_err (&port->dev, "Unknown port number!!!\n"); - return -ENODEV; + case 0: + edge_port->uart_base = UMPMEM_BASE_UART1; + edge_port->dma_address = UMPD_OEDB1_ADDRESS; + break; + case 1: + edge_port->uart_base = UMPMEM_BASE_UART2; + edge_port->dma_address = UMPD_OEDB2_ADDRESS; + break; + default: + dev_err(&port->dev, "Unknown port number!!!\n"); + return -ENODEV; } - dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x", - __func__, port_number, edge_port->uart_base, edge_port->dma_address); + dbg("%s - port_number = %d, uart_base = %04x, dma_address = %04x", + __func__, port_number, edge_port->uart_base, + edge_port->dma_address); dev = port->serial->dev; - memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount)); - init_waitqueue_head (&edge_port->delta_msr_wait); + memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); + init_waitqueue_head(&edge_port->delta_msr_wait); /* turn off loopback */ - status = TIClearLoopBack (edge_port); + status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0); if (status) { - dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n", + dev_err(&port->dev, + "%s - cannot send clear loopback command, %d\n", __func__, status); return status; } - + /* set up the port settings */ - edge_set_termios (port, port->tty->termios); + if (tty) + edge_set_termios(tty, port, port->port.tty->termios); /* open up the port */ /* milliseconds to timeout for DMA transfer */ transaction_timeout = 2; - edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) ); + edge_port->ump_read_timeout = + max(20, ((transaction_timeout * 3) / 2)); - // milliseconds to timeout for DMA transfer - open_settings = (u8)(UMP_DMA_MODE_CONTINOUS | - UMP_PIPE_TRANS_TIMEOUT_ENA | + /* milliseconds to timeout for DMA transfer */ + open_settings = (u8)(UMP_DMA_MODE_CONTINOUS | + UMP_PIPE_TRANS_TIMEOUT_ENA | (transaction_timeout << 2)); - dbg ("%s - Sending UMPC_OPEN_PORT", __func__); + dbg("%s - Sending UMPC_OPEN_PORT", __func__); /* Tell TI to open and start the port */ - status = TIWriteCommandSync (dev, - UMPC_OPEN_PORT, - (u8)(UMPM_UART1_PORT + port_number), - open_settings, - NULL, - 0); + status = send_cmd(dev, UMPC_OPEN_PORT, + (u8)(UMPM_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { - dev_err(&port->dev,"%s - cannot send open command, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot send open command, %d\n", + __func__, status); return status; } /* Start the DMA? */ - status = TIWriteCommandSync (dev, - UMPC_START_PORT, - (u8)(UMPM_UART1_PORT + port_number), - 0, - NULL, - 0); + status = send_cmd(dev, UMPC_START_PORT, + (u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); if (status) { - dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot send start DMA command, %d\n", + __func__, status); return status; } /* Clear TX and RX buffers in UMP */ - status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN); + status = purge_port(port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN); if (status) { - dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __func__, status); + dev_err(&port->dev, + "%s - cannot send clear buffers command, %d\n", + __func__, status); return status; } /* Read Initial MSR */ - status = TIReadVendorRequestSync (dev, - UMPC_READ_MSR, // Request - 0, // wValue - (__u16)(UMPM_UART1_PORT + port_number), // wIndex (Address) - &edge_port->shadow_msr, // TransferBuffer - 1); // TransferBufferLength + status = ti_vread_sync(dev, UMPC_READ_MSR, 0, + (__u16)(UMPM_UART1_PORT + port_number), + &edge_port->shadow_msr, 1); if (status) { - dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot send read MSR command, %d\n", + __func__, status); return status; } - dbg ("ShadowMSR 0x%X", edge_port->shadow_msr); - + dbg("ShadowMSR 0x%X", edge_port->shadow_msr); + /* Set Initial MCR */ edge_port->shadow_mcr = MCR_RTS | MCR_DTR; - dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr); + dbg("ShadowMCR 0x%X", edge_port->shadow_mcr); edge_serial = edge_port->edge_serial; if (mutex_lock_interruptible(&edge_serial->es_lock)) return -ERESTARTSYS; if (edge_serial->num_ports_open == 0) { - /* we are the first port to be opened, let's post the interrupt urb */ + /* we are the first port to open, post the interrupt urb */ urb = edge_serial->serial->port[0]->interrupt_in_urb; if (!urb) { - dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __func__); + dev_err(&port->dev, + "%s - no interrupt urb present, exiting\n", + __func__); status = -EINVAL; goto release_es_lock; } urb->complete = edge_interrupt_callback; urb->context = edge_serial; urb->dev = dev; - status = usb_submit_urb (urb, GFP_KERNEL); + status = usb_submit_urb(urb, GFP_KERNEL); if (status) { - dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __func__, status); + dev_err(&port->dev, + "%s - usb_submit_urb failed with value %d\n", + __func__, status); goto release_es_lock; } } @@ -2085,13 +1965,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) * reset the data toggle on the bulk endpoints to work around bug in * host controllers where things get out of sync some times */ - usb_clear_halt (dev, port->write_urb->pipe); - usb_clear_halt (dev, port->read_urb->pipe); + usb_clear_halt(dev, port->write_urb->pipe); + usb_clear_halt(dev, port->read_urb->pipe); /* start up our bulk read urb */ urb = port->read_urb; if (!urb) { - dev_err (&port->dev, "%s - no read urb present, exiting\n", __func__); + dev_err(&port->dev, "%s - no read urb present, exiting\n", + __func__); status = -EINVAL; goto unlink_int_urb; } @@ -2099,9 +1980,11 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) urb->complete = edge_bulk_in_callback; urb->context = edge_port; urb->dev = dev; - status = usb_submit_urb (urb, GFP_KERNEL); + status = usb_submit_urb(urb, GFP_KERNEL); if (status) { - dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status); + dev_err(&port->dev, + "%s - read bulk usb_submit_urb failed with value %d\n", + __func__, status); goto unlink_int_urb; } @@ -2119,7 +2002,8 @@ release_es_lock: return status; } -static void edge_close (struct usb_serial_port *port, struct file *filp) +static void edge_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; @@ -2127,18 +2011,18 @@ static void edge_close (struct usb_serial_port *port, struct file *filp) int status; dbg("%s - port %d", __func__, port->number); - + edge_serial = usb_get_serial_data(port->serial); edge_port = usb_get_serial_port_data(port); - if ((edge_serial == NULL) || (edge_port == NULL)) + if (edge_serial == NULL || edge_port == NULL) return; - - /* The bulkreadcompletion routine will check + + /* The bulkreadcompletion routine will check * this flag and dump add read data */ edge_port->close_pending = 1; /* chase the port close and flush */ - TIChasePort (edge_port, (HZ*closing_wait)/100, 1); + chase_port(edge_port, (HZ * closing_wait) / 100, 1); usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); @@ -2148,7 +2032,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp) * send a close port command to it */ dbg("%s - send umpc_close_port", __func__); port_number = port->number - port->serial->minor; - status = TIWriteCommandSync (port->serial->dev, + status = send_cmd(port->serial->dev, UMPC_CLOSE_PORT, (__u8)(UMPM_UART1_PORT + port_number), 0, @@ -2167,7 +2051,8 @@ static void edge_close (struct usb_serial_port *port, struct file *filp) dbg("%s - exited", __func__); } -static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) +static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *data, int count) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned long flags; @@ -2188,16 +2073,16 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data, count = edge_buf_put(edge_port->ep_out_buf, data, count); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - edge_send(port); + edge_send(tty); return count; } -static void edge_send(struct usb_serial_port *port) +static void edge_send(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int count, result; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct tty_struct *tty = port->tty; unsigned long flags; @@ -2223,11 +2108,12 @@ static void edge_send(struct usb_serial_port *port) spin_unlock_irqrestore(&edge_port->ep_lock, flags); - usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer); + usb_serial_debug_data(debug, &port->dev, __func__, count, + port->write_urb->transfer_buffer); /* set up our urb */ - usb_fill_bulk_urb (port->write_urb, port->serial->dev, - usb_sndbulkpipe (port->serial->dev, + usb_fill_bulk_urb(port->write_urb, port->serial->dev, + usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, count, edge_bulk_out_callback, @@ -2236,23 +2122,23 @@ static void edge_send(struct usb_serial_port *port) /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); edge_port->ep_write_urb_in_use = 0; - // TODO: reschedule edge_send - } else { + /* TODO: reschedule edge_send */ + } else edge_port->icount.tx += count; - } /* wakeup any process waiting for writes to complete */ /* there is now more room in the buffer for new writes */ - if (tty) { - /* let the tty driver wakeup if it has a special write_wakeup function */ + if (tty) tty_wakeup(tty); - } } -static int edge_write_room (struct usb_serial_port *port) +static int edge_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); int room = 0; unsigned long flags; @@ -2260,9 +2146,9 @@ static int edge_write_room (struct usb_serial_port *port) dbg("%s - port %d", __func__, port->number); if (edge_port == NULL) - return -ENODEV; + return 0; if (edge_port->close_pending == 1) - return -ENODEV; + return 0; spin_lock_irqsave(&edge_port->ep_lock, flags); room = edge_buf_space_avail(edge_port->ep_out_buf); @@ -2272,8 +2158,9 @@ static int edge_write_room (struct usb_serial_port *port) return room; } -static int edge_chars_in_buffer (struct usb_serial_port *port) +static int edge_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; @@ -2281,22 +2168,22 @@ static int edge_chars_in_buffer (struct usb_serial_port *port) dbg("%s - port %d", __func__, port->number); if (edge_port == NULL) - return -ENODEV; + return 0; if (edge_port->close_pending == 1) - return -ENODEV; + return 0; spin_lock_irqsave(&edge_port->ep_lock, flags); chars = edge_buf_data_avail(edge_port->ep_out_buf); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - dbg ("%s - returns %d", __func__, chars); + dbg("%s - returns %d", __func__, chars); return chars; } -static void edge_throttle (struct usb_serial_port *port) +static void edge_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct tty_struct *tty; int status; dbg("%s - port %d", __func__, port->number); @@ -2304,16 +2191,10 @@ static void edge_throttle (struct usb_serial_port *port) if (edge_port == NULL) return; - tty = port->tty; - if (!tty) { - dbg ("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = edge_write (port, &stop_char, 1); + status = edge_write(tty, port, &stop_char, 1); if (status <= 0) { dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status); } @@ -2326,10 +2207,10 @@ static void edge_throttle (struct usb_serial_port *port) } -static void edge_unthrottle (struct usb_serial_port *port) +static void edge_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct tty_struct *tty; int status; dbg("%s - port %d", __func__, port->number); @@ -2337,27 +2218,22 @@ static void edge_unthrottle (struct usb_serial_port *port) if (edge_port == NULL) return; - tty = port->tty; - if (!tty) { - dbg ("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = edge_write (port, &start_char, 1); + status = edge_write(tty, port, &start_char, 1); if (status <= 0) { dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status); } } - /* if we are implementing RTS/CTS, restart reads */ /* are the Edgeport will assert the RTS line */ if (C_CRTSCTS(tty)) { status = restart_read(edge_port); if (status) - dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status); + dev_err(&port->dev, + "%s - read bulk usb_submit_urb failed: %d\n", + __func__, status); } } @@ -2398,22 +2274,23 @@ static int restart_read(struct edgeport_port *edge_port) return status; } -static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) +static void change_port_settings(struct tty_struct *tty, + struct edgeport_port *edge_port, struct ktermios *old_termios) { struct ump_uart_config *config; - struct tty_struct *tty; int baud; unsigned cflag; int status; - int port_number = edge_port->port->number - edge_port->port->serial->minor; + int port_number = edge_port->port->number - + edge_port->port->serial->minor; dbg("%s - port %d", __func__, edge_port->port->number); - tty = edge_port->port->tty; - config = kmalloc (sizeof (*config), GFP_KERNEL); if (!config) { - dev_err (&edge_port->port->dev, "%s - out of memory\n", __func__); + *tty->termios = *old_termios; + dev_err(&edge_port->port->dev, "%s - out of memory\n", + __func__); return; } @@ -2427,22 +2304,22 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi config->bUartMode = (__u8)(edge_port->bUartMode); switch (cflag & CSIZE) { - case CS5: - config->bDataBits = UMP_UART_CHAR5BITS; - dbg ("%s - data bits = 5", __func__); - break; - case CS6: - config->bDataBits = UMP_UART_CHAR6BITS; - dbg ("%s - data bits = 6", __func__); - break; - case CS7: - config->bDataBits = UMP_UART_CHAR7BITS; - dbg ("%s - data bits = 7", __func__); - break; - default: - case CS8: - config->bDataBits = UMP_UART_CHAR8BITS; - dbg ("%s - data bits = 8", __func__); + case CS5: + config->bDataBits = UMP_UART_CHAR5BITS; + dbg("%s - data bits = 5", __func__); + break; + case CS6: + config->bDataBits = UMP_UART_CHAR6BITS; + dbg("%s - data bits = 6", __func__); + break; + case CS7: + config->bDataBits = UMP_UART_CHAR7BITS; + dbg("%s - data bits = 7", __func__); + break; + default: + case CS8: + config->bDataBits = UMP_UART_CHAR8BITS; + dbg("%s - data bits = 8", __func__); break; } @@ -2457,7 +2334,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi dbg("%s - parity = even", __func__); } } else { - config->bParity = UMP_UART_NOPARITY; + config->bParity = UMP_UART_NOPARITY; dbg("%s - parity = none", __func__); } @@ -2480,29 +2357,26 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi restart_read(edge_port); } - /* if we are implementing XON/XOFF, set the start and stop character in the device */ - if (I_IXOFF(tty) || I_IXON(tty)) { - config->cXon = START_CHAR(tty); - config->cXoff = STOP_CHAR(tty); + /* if we are implementing XON/XOFF, set the start and stop + character in the device */ + config->cXon = START_CHAR(tty); + config->cXoff = STOP_CHAR(tty); - /* if we are implementing INBOUND XON/XOFF */ - if (I_IXOFF(tty)) { - config->wFlags |= UMP_MASK_UART_FLAGS_IN_X; - dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", - __func__, config->cXon, config->cXoff); - } else { - dbg ("%s - INBOUND XON/XOFF is disabled", __func__); - } + /* if we are implementing INBOUND XON/XOFF */ + if (I_IXOFF(tty)) { + config->wFlags |= UMP_MASK_UART_FLAGS_IN_X; + dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", + __func__, config->cXon, config->cXoff); + } else + dbg("%s - INBOUND XON/XOFF is disabled", __func__); - /* if we are implementing OUTBOUND XON/XOFF */ - if (I_IXON(tty)) { - config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X; - dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", - __func__, config->cXon, config->cXoff); - } else { - dbg ("%s - OUTBOUND XON/XOFF is disabled", __func__); - } - } + /* if we are implementing OUTBOUND XON/XOFF */ + if (I_IXON(tty)) { + config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X; + dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", + __func__, config->cXon, config->cXoff); + } else + dbg("%s - OUTBOUND XON/XOFF is disabled", __func__); tty->termios->c_cflag &= ~CMSPAR; @@ -2519,41 +2393,36 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi /* FIXME: Recompute actual baud from divisor here */ - dbg ("%s - baud rate = %d, wBaudRate = %d", __func__, baud, config->wBaudRate); + dbg("%s - baud rate = %d, wBaudRate = %d", __func__, baud, + config->wBaudRate); - dbg ("wBaudRate: %d", (int)(461550L / config->wBaudRate)); - dbg ("wFlags: 0x%x", config->wFlags); - dbg ("bDataBits: %d", config->bDataBits); - dbg ("bParity: %d", config->bParity); - dbg ("bStopBits: %d", config->bStopBits); - dbg ("cXon: %d", config->cXon); - dbg ("cXoff: %d", config->cXoff); - dbg ("bUartMode: %d", config->bUartMode); + dbg("wBaudRate: %d", (int)(461550L / config->wBaudRate)); + dbg("wFlags: 0x%x", config->wFlags); + dbg("bDataBits: %d", config->bDataBits); + dbg("bParity: %d", config->bParity); + dbg("bStopBits: %d", config->bStopBits); + dbg("cXon: %d", config->cXon); + dbg("cXoff: %d", config->cXoff); + dbg("bUartMode: %d", config->bUartMode); /* move the word values into big endian mode */ - cpu_to_be16s (&config->wFlags); - cpu_to_be16s (&config->wBaudRate); + cpu_to_be16s(&config->wFlags); + cpu_to_be16s(&config->wBaudRate); - status = TIWriteCommandSync (edge_port->port->serial->dev, - UMPC_SET_CONFIG, + status = send_cmd(edge_port->port->serial->dev, UMPC_SET_CONFIG, (__u8)(UMPM_UART1_PORT + port_number), - 0, - (__u8 *)config, - sizeof(*config)); - if (status) { - dbg ("%s - error %d when trying to write config to device", + 0, (__u8 *)config, sizeof(*config)); + if (status) + dbg("%s - error %d when trying to write config to device", __func__, status); - } - - kfree (config); - + kfree(config); return; } -static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) +static void edge_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct tty_struct *tty = port->tty; unsigned int cflag; cflag = tty->termios->c_cflag; @@ -2562,20 +2431,19 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old tty->termios->c_cflag, tty->termios->c_iflag); dbg("%s - old clfag %08x old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag); - dbg("%s - port %d", __func__, port->number); if (edge_port == NULL) return; - /* change the port settings to the new ones specified */ - change_port_settings (edge_port, old_termios); - + change_port_settings(tty, edge_port, old_termios); return; } -static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) +static int edge_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int mcr; unsigned long flags; @@ -2601,13 +2469,13 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig edge_port->shadow_mcr = mcr; spin_unlock_irqrestore(&edge_port->ep_lock, flags); - TIRestoreMCR (edge_port, mcr); - + restore_mcr(edge_port, mcr); return 0; } -static int edge_tiocmget(struct usb_serial_port *port, struct file *file) +static int edge_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int result = 0; unsigned int msr; @@ -2634,7 +2502,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file) return result; } -static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct __user *retinfo) +static int get_serial_info(struct edgeport_port *edge_port, + struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -2652,18 +2521,16 @@ static int get_serial_info (struct edgeport_port *edge_port, struct serial_struc tmp.baud_base = 9600; tmp.close_delay = 5*HZ; tmp.closing_wait = closing_wait; -// tmp.custom_divisor = state->custom_divisor; -// tmp.hub6 = state->hub6; -// tmp.io_type = state->io_type; - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; return 0; } -static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) +static int edge_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct async_icount cnow; struct async_icount cprev; @@ -2671,81 +2538,64 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); switch (cmd) { - case TIOCINQ: - dbg("%s - (%d) TIOCINQ", __func__, port->number); -// return get_number_bytes_avail(edge_port, (unsigned int *) arg); - break; - - case TIOCSERGETLSR: - dbg("%s - (%d) TIOCSERGETLSR", __func__, port->number); -// return get_lsr_info(edge_port, (unsigned int *) arg); - break; - - case TIOCGSERIAL: - dbg("%s - (%d) TIOCGSERIAL", __func__, port->number); - return get_serial_info(edge_port, (struct serial_struct __user *) arg); - break; - - case TIOCSSERIAL: - dbg("%s - (%d) TIOCSSERIAL", __func__, port->number); - break; - - case TIOCMIWAIT: - dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); - cprev = edge_port->icount; - while (1) { - interruptible_sleep_on(&edge_port->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - cnow = edge_port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; + case TIOCGSERIAL: + dbg("%s - (%d) TIOCGSERIAL", __func__, port->number); + return get_serial_info(edge_port, + (struct serial_struct __user *) arg); + case TIOCMIWAIT: + dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); + cprev = edge_port->icount; + while (1) { + interruptible_sleep_on(&edge_port->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + cnow = edge_port->icount; + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + return 0; } - /* not reached */ - break; - - case TIOCGICOUNT: - dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, - port->number, edge_port->icount.rx, edge_port->icount.tx); - if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount))) - return -EFAULT; - return 0; + cprev = cnow; + } + /* not reached */ + break; + case TIOCGICOUNT: + dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, + port->number, edge_port->icount.rx, edge_port->icount.tx); + if (copy_to_user((void __user *)arg, &edge_port->icount, + sizeof(edge_port->icount))) + return -EFAULT; + return 0; } - return -ENOIOCTLCMD; } -static void edge_break (struct usb_serial_port *port, int break_state) +static void edge_break(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status; + int bv = 0; /* Off */ - dbg ("%s - state = %d", __func__, break_state); + dbg("%s - state = %d", __func__, break_state); /* chase the port close */ - TIChasePort (edge_port, 0, 0); + chase_port(edge_port, 0, 0); - if (break_state == -1) { - status = TISetBreak (edge_port); - } else { - status = TIClearBreak (edge_port); - } - if (status) { - dbg ("%s - error %d sending break set/clear command.", + if (break_state == -1) + bv = 1; /* On */ + status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv); + if (status) + dbg("%s - error %d sending break set/clear command.", __func__, status); - } } -static int edge_startup (struct usb_serial *serial) +static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; @@ -2765,9 +2615,9 @@ static int edge_startup (struct usb_serial *serial) edge_serial->serial = serial; usb_set_serial_data(serial, edge_serial); - status = TIDownloadFirmware (edge_serial); + status = download_fw(edge_serial); if (status) { - kfree (edge_serial); + kfree(edge_serial); return status; } @@ -2775,13 +2625,15 @@ static int edge_startup (struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + dev_err(&serial->dev->dev, "%s - Out of memory\n", + __func__); goto cleanup; } spin_lock_init(&edge_port->ep_lock); edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE); if (edge_port->ep_out_buf == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + dev_err(&serial->dev->dev, "%s - Out of memory\n", + __func__); kfree(edge_port); goto cleanup; } @@ -2790,27 +2642,27 @@ static int edge_startup (struct usb_serial *serial) usb_set_serial_port_data(serial->port[i], edge_port); edge_port->bUartMode = default_uart_mode; } - + return 0; cleanup: - for (--i; i>=0; --i) { + for (--i; i >= 0; --i) { edge_port = usb_get_serial_port_data(serial->port[i]); edge_buf_free(edge_port->ep_out_buf); kfree(edge_port); usb_set_serial_port_data(serial->port[i], NULL); } - kfree (edge_serial); + kfree(edge_serial); usb_set_serial_data(serial, NULL); return -ENOMEM; } -static void edge_shutdown (struct usb_serial *serial) +static void edge_shutdown(struct usb_serial *serial) { int i; struct edgeport_port *edge_port; - dbg ("%s", __func__); + dbg("%s", __func__); for (i = 0; i < serial->num_ports; ++i) { edge_port = usb_get_serial_port_data(serial->port[i]); @@ -2852,7 +2704,8 @@ static ssize_t store_uart_mode(struct device *dev, return count; } -static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, store_uart_mode); +static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, + store_uart_mode); static int edge_create_sysfs_attrs(struct usb_serial_port *port) { @@ -2922,9 +2775,9 @@ static void edge_buf_free(struct edge_buf *eb) static void edge_buf_clear(struct edge_buf *eb) { - if (eb != NULL) - eb->buf_get = eb->buf_put; - /* equivalent to a get of all data available */ + if (eb != NULL) + eb->buf_get = eb->buf_put; + /* equivalent to a get of all data available */ } @@ -2937,10 +2790,9 @@ static void edge_buf_clear(struct edge_buf *eb) static unsigned int edge_buf_data_avail(struct edge_buf *eb) { - if (eb != NULL) - return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size); - else + if (eb == NULL) return 0; + return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size); } @@ -2953,10 +2805,9 @@ static unsigned int edge_buf_data_avail(struct edge_buf *eb) static unsigned int edge_buf_space_avail(struct edge_buf *eb) { - if (eb != NULL) - return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size); - else + if (eb == NULL) return 0; + return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size); } @@ -3113,7 +2964,7 @@ static int __init edgeport_init(void) if (retval) goto failed_2port_device_register; retval = usb_register(&io_driver); - if (retval) + if (retval) goto failed_usb_register; info(DRIVER_DESC " " DRIVER_VERSION); return 0; @@ -3125,11 +2976,11 @@ failed_1port_device_register: return retval; } -static void __exit edgeport_exit (void) +static void __exit edgeport_exit(void) { - usb_deregister (&io_driver); - usb_serial_deregister (&edgeport_1port_device); - usb_serial_deregister (&edgeport_2port_device); + usb_deregister(&io_driver); + usb_serial_deregister(&edgeport_1port_device); + usb_serial_deregister(&edgeport_2port_device); } module_init(edgeport_init); @@ -3151,8 +3002,8 @@ module_param(closing_wait, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs"); module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device"); +MODULE_PARM_DESC(ignore_cpu_rev, + "Ignore the cpu revision when connecting to a device"); module_param(default_uart_mode, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ..."); - diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index d9fb3768a2d7..832a5a4f3cb3 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -53,7 +53,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "ipaq.h" @@ -74,19 +74,21 @@ static int connect_retries = KP_RETRIES; static int initial_wait; /* Function prototypes for an ipaq */ -static int ipaq_open (struct usb_serial_port *port, struct file *filp); -static void ipaq_close (struct usb_serial_port *port, struct file *filp); -static int ipaq_startup (struct usb_serial *serial); -static void ipaq_shutdown (struct usb_serial *serial); -static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, - int count); -static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, - int count); +static int ipaq_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void ipaq_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static int ipaq_startup(struct usb_serial *serial); +static void ipaq_shutdown(struct usb_serial *serial); +static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static int ipaq_write_bulk(struct usb_serial_port *port, + const unsigned char *buf, int count); static void ipaq_write_gather(struct usb_serial_port *port); -static void ipaq_read_bulk_callback (struct urb *urb); +static void ipaq_read_bulk_callback(struct urb *urb); static void ipaq_write_bulk_callback(struct urb *urb); -static int ipaq_write_room(struct usb_serial_port *port); -static int ipaq_chars_in_buffer(struct usb_serial_port *port); +static int ipaq_write_room(struct tty_struct *tty); +static int ipaq_chars_in_buffer(struct tty_struct *tty); static void ipaq_destroy_lists(struct usb_serial_port *port); @@ -550,7 +552,7 @@ static struct usb_device_id ipaq_id_table [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, ipaq_id_table); +MODULE_DEVICE_TABLE(usb, ipaq_id_table); static struct usb_driver ipaq_driver = { .name = "ipaq", @@ -591,7 +593,8 @@ static spinlock_t write_list_lock; static int bytes_in; static int bytes_out; -static int ipaq_open(struct usb_serial_port *port, struct file *filp) +static int ipaq_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; struct ipaq_private *priv; @@ -617,9 +620,9 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) { pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL); - if (pkt == NULL) { + if (pkt == NULL) goto enomem; - } + pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL); if (pkt->data == NULL) { kfree(pkt); @@ -637,21 +640,24 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) * discipline instead of queueing. */ - port->tty->low_latency = 1; - port->tty->raw = 1; - port->tty->real_raw = 1; - + if (tty) { + tty->low_latency = 1; + /* FIXME: These two are bogus */ + tty->raw = 1; + tty->real_raw = 1; + } /* * Lose the small buffers usbserial provides. Make larger ones. */ kfree(port->bulk_in_buffer); - kfree(port->bulk_out_buffer); port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL); if (port->bulk_in_buffer == NULL) { port->bulk_out_buffer = NULL; /* prevent double free */ goto enomem; } + + kfree(port->bulk_out_buffer); port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL); if (port->bulk_out_buffer == NULL) { kfree(port->bulk_in_buffer); @@ -661,8 +667,9 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) port->read_urb->transfer_buffer = port->bulk_in_buffer; port->write_urb->transfer_buffer = port->bulk_out_buffer; port->read_urb->transfer_buffer_length = URBDATA_SIZE; - port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE; - + port->bulk_out_size = port->write_urb->transfer_buffer_length + = URBDATA_SIZE; + msleep(1000*initial_wait); /* @@ -691,13 +698,15 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) /* Start reading from the device */ usb_fill_bulk_urb(port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, - ipaq_read_bulk_callback, port); + usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ipaq_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) { - err("%s - failed submitting read urb, error %d", __func__, result); + err("%s - failed submitting read urb, error %d", + __func__, result); goto error; } @@ -713,12 +722,13 @@ error: } -static void ipaq_close(struct usb_serial_port *port, struct file *filp) +static void ipaq_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct ipaq_private *priv = usb_get_serial_port_data(port); dbg("%s - port %d", __func__, port->number); - + /* * shut down bulk read and write */ @@ -728,7 +738,8 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp) kfree(priv); usb_set_serial_port_data(port, NULL); - /* Uncomment the following line if you want to see some statistics in your syslog */ + /* Uncomment the following line if you want to see some statistics + * in your syslog */ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ } @@ -748,9 +759,10 @@ static void ipaq_read_bulk_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); @@ -759,18 +771,20 @@ static void ipaq_read_bulk_callback(struct urb *urb) } /* Continue trying to always read */ - usb_fill_bulk_urb(port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, - ipaq_read_bulk_callback, port); + usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ipaq_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", __func__, result); + err("%s - failed resubmitting read urb, error %d", + __func__, result); return; } -static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, - int count) +static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { const unsigned char *current_position = buf; int bytes_sent = 0; @@ -780,9 +794,8 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, while (count > 0) { transfer_size = min(count, PACKET_SIZE); - if (ipaq_write_bulk(port, current_position, transfer_size)) { + if (ipaq_write_bulk(port, current_position, transfer_size)) break; - } current_position += transfer_size; bytes_sent += transfer_size; count -= transfer_size; @@ -790,10 +803,10 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, } return bytes_sent; -} +} -static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, - int count) +static int ipaq_write_bulk(struct usb_serial_port *port, + const unsigned char *buf, int count) { struct ipaq_private *priv = usb_get_serial_port_data(port); struct ipaq_packet *pkt = NULL; @@ -830,9 +843,9 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu ipaq_write_gather(port); spin_unlock_irqrestore(&write_list_lock, flags); result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (result) { - err("%s - failed submitting write urb, error %d", __func__, result); - } + if (result) + err("%s - failed submitting write urb, error %d", + __func__, result); } else { spin_unlock_irqrestore(&write_list_lock, flags); } @@ -859,16 +872,15 @@ static void ipaq_write_gather(struct usb_serial_port *port) list_move(&pkt->list, &priv->freelist); priv->free_len += PACKET_SIZE; } - if (room == 0) { + if (room == 0) break; - } } count = URBDATA_SIZE - room; - usb_fill_bulk_urb(port->write_urb, serial->dev, - usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback, - port); + usb_fill_bulk_urb(port->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), + port->write_urb->transfer_buffer, count, + ipaq_write_bulk_callback, port); return; } @@ -893,9 +905,9 @@ static void ipaq_write_bulk_callback(struct urb *urb) ipaq_write_gather(port); spin_unlock_irqrestore(&write_list_lock, flags); result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (result) { - err("%s - failed submitting write urb, error %d", __func__, result); - } + if (result) + err("%s - failed submitting write urb, error %d", + __func__, result); } else { priv->active = 0; spin_unlock_irqrestore(&write_list_lock, flags); @@ -904,16 +916,18 @@ static void ipaq_write_bulk_callback(struct urb *urb) usb_serial_port_softint(port); } -static int ipaq_write_room(struct usb_serial_port *port) +static int ipaq_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ipaq_private *priv = usb_get_serial_port_data(port); dbg("%s - freelen %d", __func__, priv->free_len); return priv->free_len; } -static int ipaq_chars_in_buffer(struct usb_serial_port *port) +static int ipaq_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ipaq_private *priv = usb_get_serial_port_data(port); dbg("%s - queuelen %d", __func__, priv->queue_len); @@ -944,7 +958,7 @@ static int ipaq_startup(struct usb_serial *serial) serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } - return usb_reset_configuration (serial->dev); + return usb_reset_configuration(serial->dev); } static void ipaq_shutdown(struct usb_serial *serial) @@ -957,7 +971,7 @@ static int __init ipaq_init(void) int retval; spin_lock_init(&write_list_lock); retval = usb_serial_register(&ipaq_device); - if (retval) + if (retval) goto failed_usb_serial_register; info(DRIVER_DESC " " DRIVER_VERSION); if (vendor) { @@ -967,7 +981,7 @@ static int __init ipaq_init(void) retval = usb_register(&ipaq_driver); if (retval) goto failed_usb_register; - + return 0; failed_usb_register: usb_serial_deregister(&ipaq_device); @@ -986,8 +1000,8 @@ static void __exit ipaq_exit(void) module_init(ipaq_init); module_exit(ipaq_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); @@ -1000,7 +1014,9 @@ module_param(product, ushort, 0); MODULE_PARM_DESC(product, "User specified USB idProduct"); module_param(connect_retries, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)"); +MODULE_PARM_DESC(connect_retries, + "Maximum number of connect retries (one second each)"); module_param(initial_wait, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(initial_wait, "Time to wait before attempting a connection (in seconds)"); +MODULE_PARM_DESC(initial_wait, + "Time to wait before attempting a connection (in seconds)"); diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index bc85ca5c1c37..a842025b9b57 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -10,27 +10,27 @@ * (at your option) any later version. * * All information about the device was acquired using SnoopyPro - * on MSFT's O/S, and examing the MSFT drivers' debug output + * on MSFT's O/S, and examing the MSFT drivers' debug output * (insanely left _on_ in the enduser version) * * It was written out of frustration with the IPWireless USB modem * supplied by Axity3G/Sentech South Africa not supporting * Linux whatsoever. * - * Nobody provided any proprietary information that was not already + * Nobody provided any proprietary information that was not already * available for this device. - * - * The modem adheres to the "3GPP TS 27.007 AT command set for 3G - * User Equipment (UE)" standard, available from + * + * The modem adheres to the "3GPP TS 27.007 AT command set for 3G + * User Equipment (UE)" standard, available from * http://www.3gpp.org/ftp/Specs/html-info/27007.htm * * The code was only tested the IPWireless handheld modem distributed * in South Africa by Sentech. - * + * * It may work for Woosh Inc in .nz too, as it appears they use the * same kit. * - * There is still some work to be done in terms of handling + * There is still some work to be done in terms of handling * DCD, DTR, RTS, CTS which are currently faked. * It's good enough for PPP at this point. It's based off all kinds of * code found in usb/serial and usb/class @@ -47,7 +47,7 @@ #include <linux/spinlock.h> #include <linux/usb.h> #include <linux/usb/serial.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> /* * Version Information @@ -64,7 +64,7 @@ /* Message sizes */ #define EVENT_BUFFER_SIZE 0xFF -#define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff)) +#define CHAR2INT16(c1, c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff)) #define NUM_BULK_URBS 24 #define NUM_CONTROL_URBS 16 @@ -94,33 +94,34 @@ enum { /* data bits */ #define ipw_dtb_7 0x700 -#define ipw_dtb_8 0x810 // ok so the define is misleading, I know, but forces 8,n,1 - // I mean, is there a point to any other setting these days? :) +#define ipw_dtb_8 0x810 /* ok so the define is misleading, I know, but forces 8,n,1 */ + /* I mean, is there a point to any other setting these days? :) */ /* usb control request types : */ -#define IPW_SIO_RXCTL 0x00 // control bulk rx channel transmissions, value=1/0 (on/off) -#define IPW_SIO_SET_BAUD 0x01 // set baud, value=requested ipw_sio_bxxxx -#define IPW_SIO_SET_LINE 0x03 // set databits, parity. value=ipw_dtb_x -#define IPW_SIO_SET_PIN 0x03 // set/clear dtr/rts value=ipw_pin_xxx -#define IPW_SIO_POLL 0x08 // get serial port status byte, call with value=0 -#define IPW_SIO_INIT 0x11 // initializes ? value=0 (appears as first thing todo on open) -#define IPW_SIO_PURGE 0x12 // purge all transmissions?, call with value=numchar_to_purge -#define IPW_SIO_HANDFLOW 0x13 // set xon/xoff limits value=0, and a buffer of 0x10 bytes -#define IPW_SIO_SETCHARS 0x13 // set the flowcontrol special chars, value=0, buf=6 bytes, - // last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13 +#define IPW_SIO_RXCTL 0x00 /* control bulk rx channel transmissions, value=1/0 (on/off) */ +#define IPW_SIO_SET_BAUD 0x01 /* set baud, value=requested ipw_sio_bxxxx */ +#define IPW_SIO_SET_LINE 0x03 /* set databits, parity. value=ipw_dtb_x */ +#define IPW_SIO_SET_PIN 0x03 /* set/clear dtr/rts value=ipw_pin_xxx */ +#define IPW_SIO_POLL 0x08 /* get serial port status byte, call with value=0 */ +#define IPW_SIO_INIT 0x11 /* initializes ? value=0 (appears as first thing todo on open) */ +#define IPW_SIO_PURGE 0x12 /* purge all transmissions?, call with value=numchar_to_purge */ +#define IPW_SIO_HANDFLOW 0x13 /* set xon/xoff limits value=0, and a buffer of 0x10 bytes */ +#define IPW_SIO_SETCHARS 0x13 /* set the flowcontrol special chars, value=0, buf=6 bytes, */ + /* last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13 */ /* values used for request IPW_SIO_SET_PIN */ #define IPW_PIN_SETDTR 0x101 #define IPW_PIN_SETRTS 0x202 #define IPW_PIN_CLRDTR 0x100 -#define IPW_PIN_CLRRTS 0x200 // unconfirmed +#define IPW_PIN_CLRRTS 0x200 /* unconfirmed */ /* values used for request IPW_SIO_RXCTL */ #define IPW_RXBULK_ON 1 #define IPW_RXBULK_OFF 0 /* various 16 byte hardcoded transferbuffers used by flow control */ -#define IPW_BYTES_FLOWINIT { 0x01, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +#define IPW_BYTES_FLOWINIT { 0x01, 0, 0, 0, 0x40, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0 } /* Interpretation of modem status lines */ /* These need sorting out by individually connecting pins and checking @@ -132,17 +133,6 @@ enum { #define IPW_CTS ((1<<5) | (1<<4)) #define IPW_WANTS_TO_SEND 0x30 -//#define IPW_DTR /* Data Terminal Ready */ -//#define IPW_CTS /* Clear To Send */ -//#define IPW_CD /* Carrier Detect */ -//#define IPW_DSR /* Data Set Ready */ -//#define IPW_RxD /* Receive pin */ - -//#define IPW_LE -//#define IPW_RTS -//#define IPW_ST -//#define IPW_SR -//#define IPW_RI /* Ring Indicator */ static struct usb_device_id usb_ipw_ids[] = { { USB_DEVICE(IPW_VID, IPW_PID) }, @@ -177,9 +167,10 @@ static void ipw_read_bulk_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); @@ -187,19 +178,22 @@ static void ipw_read_bulk_callback(struct urb *urb) } /* Continue trying to always read */ - usb_fill_bulk_urb (port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, + usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - ipw_read_bulk_callback, port); + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ipw_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); return; } -static int ipw_open(struct usb_serial_port *port, struct file *filp) +static int ipw_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_device *dev = port->serial->dev; u8 buf_flow_static[16] = IPW_BYTES_FLOWINIT; @@ -212,29 +206,33 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp) if (!buf_flow_init) return -ENOMEM; - if (port->tty) - port->tty->low_latency = 1; - - /* --1: Tell the modem to initialize (we think) From sniffs this is always the - * first thing that gets sent to the modem during opening of the device */ - dbg("%s: Sending SIO_INIT (we guess)",__func__); - result = usb_control_msg(dev, usb_sndctrlpipe(dev,0), - IPW_SIO_INIT, - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - 0, - 0, /* index */ - NULL, - 0, - 100000); + if (tty) + tty->low_latency = 1; + + /* --1: Tell the modem to initialize (we think) From sniffs this is + * always the first thing that gets sent to the modem during + * opening of the device */ + dbg("%s: Sending SIO_INIT (we guess)", __func__); + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + IPW_SIO_INIT, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + 0, + 0, /* index */ + NULL, + 0, + 100000); if (result < 0) - dev_err(&port->dev, "Init of modem failed (error = %d)\n", result); + dev_err(&port->dev, + "Init of modem failed (error = %d)\n", result); /* reset the bulk pipes */ - usb_clear_halt(dev, usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress)); - usb_clear_halt(dev, usb_sndbulkpipe(dev, port->bulk_out_endpointAddress)); + usb_clear_halt(dev, + usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress)); + usb_clear_halt(dev, + usb_sndbulkpipe(dev, port->bulk_out_endpointAddress)); - /*--2: Start reading from the device */ - dbg("%s: setting up bulk read callback",__func__); + /*--2: Start reading from the device */ + dbg("%s: setting up bulk read callback", __func__); usb_fill_bulk_urb(port->read_urb, dev, usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), port->bulk_in_buffer, @@ -242,66 +240,72 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp) ipw_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result < 0) - dbg("%s - usb_submit_urb(read bulk) failed with status %d", __func__, result); + dbg("%s - usb_submit_urb(read bulk) failed with status %d", + __func__, result); /*--3: Tell the modem to open the floodgates on the rx bulk channel */ - dbg("%s:asking modem for RxRead (RXBULK_ON)",__func__); + dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_RXCTL, - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - IPW_RXBULK_ON, - 0, /* index */ - NULL, - 0, - 100000); - if (result < 0) - dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result); + IPW_SIO_RXCTL, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + IPW_RXBULK_ON, + 0, /* index */ + NULL, + 0, + 100000); + if (result < 0) + dev_err(&port->dev, + "Enabling bulk RxRead failed (error = %d)\n", result); /*--4: setup the initial flowcontrol */ - dbg("%s:setting init flowcontrol (%s)",__func__,buf_flow_init); + dbg("%s:setting init flowcontrol (%s)", __func__, buf_flow_init); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_HANDFLOW, - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - 0, - 0, - buf_flow_init, - 0x10, - 200000); + IPW_SIO_HANDFLOW, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + 0, + 0, + buf_flow_init, + 0x10, + 200000); if (result < 0) - dev_err(&port->dev, "initial flowcontrol failed (error = %d)\n", result); + dev_err(&port->dev, + "initial flowcontrol failed (error = %d)\n", result); /*--5: raise the dtr */ - dbg("%s:raising dtr",__func__); + dbg("%s:raising dtr", __func__); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_SET_PIN, - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - IPW_PIN_SETDTR, - 0, - NULL, - 0, - 200000); + IPW_SIO_SET_PIN, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + IPW_PIN_SETDTR, + 0, + NULL, + 0, + 200000); if (result < 0) - dev_err(&port->dev, "setting dtr failed (error = %d)\n", result); + dev_err(&port->dev, + "setting dtr failed (error = %d)\n", result); /*--6: raise the rts */ - dbg("%s:raising rts",__func__); + dbg("%s:raising rts", __func__); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_SET_PIN, - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - IPW_PIN_SETRTS, - 0, - NULL, - 0, - 200000); + IPW_SIO_SET_PIN, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + IPW_PIN_SETRTS, + 0, + NULL, + 0, + 200000); if (result < 0) - dev_err(&port->dev, "setting dtr failed (error = %d)\n", result); - + dev_err(&port->dev, + "setting dtr failed (error = %d)\n", result); + kfree(buf_flow_init); return 0; } -static void ipw_close(struct usb_serial_port *port, struct file * filp) +static void ipw_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_device *dev = port->serial->dev; int result; @@ -312,56 +316,62 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp) } /*--1: drop the dtr */ - dbg("%s:dropping dtr",__func__); + dbg("%s:dropping dtr", __func__); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_SET_PIN, - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - IPW_PIN_CLRDTR, - 0, - NULL, - 0, - 200000); + IPW_SIO_SET_PIN, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + IPW_PIN_CLRDTR, + 0, + NULL, + 0, + 200000); if (result < 0) - dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result); + dev_err(&port->dev, "dropping dtr failed (error = %d)\n", + result); /*--2: drop the rts */ - dbg("%s:dropping rts",__func__); + dbg("%s:dropping rts", __func__); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - IPW_PIN_CLRRTS, - 0, - NULL, - 0, - 200000); + IPW_SIO_SET_PIN, USB_TYPE_VENDOR | + USB_RECIP_INTERFACE | USB_DIR_OUT, + IPW_PIN_CLRRTS, + 0, + NULL, + 0, + 200000); if (result < 0) - dev_err(&port->dev, "dropping rts failed (error = %d)\n", result); + dev_err(&port->dev, + "dropping rts failed (error = %d)\n", result); /*--3: purge */ - dbg("%s:sending purge",__func__); + dbg("%s:sending purge", __func__); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - 0x03, - 0, - NULL, - 0, - 200000); + IPW_SIO_PURGE, USB_TYPE_VENDOR | + USB_RECIP_INTERFACE | USB_DIR_OUT, + 0x03, + 0, + NULL, + 0, + 200000); if (result < 0) dev_err(&port->dev, "purge failed (error = %d)\n", result); - /* send RXBULK_off (tell modem to stop transmitting bulk data on rx chan) */ + /* send RXBULK_off (tell modem to stop transmitting bulk data on + rx chan) */ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - IPW_SIO_RXCTL, - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - IPW_RXBULK_OFF, - 0, /* index */ - NULL, - 0, - 100000); + IPW_SIO_RXCTL, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + IPW_RXBULK_OFF, + 0, /* index */ + NULL, + 0, + 100000); if (result < 0) - dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)\n", result); + dev_err(&port->dev, + "Disabling bulk RxRead failed (error = %d)\n", result); /* shutdown any in-flight urbs that we know about */ usb_kill_urb(port->read_urb); @@ -384,13 +394,14 @@ static void ipw_write_bulk_callback(struct urb *urb) usb_serial_port_softint(port); } -static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) +static int ipw_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { struct usb_device *dev = port->serial->dev; int ret; dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__, - count, in_interrupt() ); + count, in_interrupt()); if (count == 0) { dbg("%s - write request of 0 bytes", __func__); @@ -421,13 +432,14 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (ret != 0) { port->write_urb_busy = 0; - dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __func__, ret); + dbg("%s - usb_submit_urb(write bulk) failed with error = %d", + __func__, ret); return ret; } dbg("%s returning %d", __func__, count); return count; -} +} static int ipw_probe(struct usb_serial_port *port) { @@ -486,8 +498,8 @@ module_init(usb_ipw_init); module_exit(usb_ipw_exit); /* Module information */ -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 004d57385a75..e59155c6607d 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -19,7 +19,12 @@ * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com> * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver + * + * 2008_Jun_02 Felipe Balbi <me@felipebalbi.com> + * Introduced common header to be used also in USB Gadget Framework. + * Still needs some other style fixes. * * 2007_Jun_21 Alan Cox <alan@redhat.com> * Minimal cleanups for some of the driver problens and tty layer abuse. @@ -59,9 +64,10 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> +#include <linux/usb/irda.h> /* * Version Information @@ -70,100 +76,77 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" #define DRIVER_DESC "USB IR Dongle driver" -/* USB IrDA class spec information */ -#define USB_CLASS_IRDA 0x02 -#define USB_DT_IRDA 0x21 -#define IU_REQ_GET_CLASS_DESC 0x06 -#define SPEED_2400 0x01 -#define SPEED_9600 0x02 -#define SPEED_19200 0x03 -#define SPEED_38400 0x04 -#define SPEED_57600 0x05 -#define SPEED_115200 0x06 -#define SPEED_576000 0x07 -#define SPEED_1152000 0x08 -#define SPEED_4000000 0x09 - -struct irda_class_desc { - u8 bLength; - u8 bDescriptorType; - u16 bcdSpecRevision; - u8 bmDataSize; - u8 bmWindowSize; - u8 bmMinTurnaroundTime; - u16 wBaudRate; - u8 bmAdditionalBOFs; - u8 bIrdaRateSniff; - u8 bMaxUnicastList; -} __attribute__ ((packed)); - static int debug; /* if overridden by the user, then use their value for the size of the read and * write urbs */ static int buffer_size; + /* if overridden by the user, then use the specified number of XBOFs */ static int xbof = -1; static int ir_startup (struct usb_serial *serial); -static int ir_open (struct usb_serial_port *port, struct file *filep); -static void ir_close (struct usb_serial_port *port, struct file *filep); -static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count); +static int ir_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filep); +static void ir_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filep); +static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); static void ir_write_bulk_callback (struct urb *urb); static void ir_read_bulk_callback (struct urb *urb); -static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); +static void ir_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios); /* Not that this lot means you can only have one per system */ -static u8 ir_baud = 0; -static u8 ir_xbof = 0; -static u8 ir_add_bof = 0; +static u8 ir_baud; +static u8 ir_xbof; +static u8 ir_add_bof; -static struct usb_device_id id_table [] = { +static struct usb_device_id ir_id_table[] = { { USB_DEVICE(0x050f, 0x0180) }, /* KC Technology, KC-180 */ { USB_DEVICE(0x08e9, 0x0100) }, /* XTNDAccess */ { USB_DEVICE(0x09c4, 0x0011) }, /* ACTiSys ACT-IR2000U */ - { USB_INTERFACE_INFO (USB_CLASS_APP_SPEC, USB_CLASS_IRDA, 0) }, + { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, USB_SUBCLASS_IRDA, 0) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, ir_id_table); static struct usb_driver ir_driver = { - .name = "ir-usb", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, + .name = "ir-usb", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = ir_id_table, + .no_dynamic_id = 1, }; - static struct usb_serial_driver ir_device = { - .driver = { - .owner = THIS_MODULE, - .name = "ir-usb", + .driver = { + .owner = THIS_MODULE, + .name = "ir-usb", }, - .description = "IR Dongle", - .usb_driver = &ir_driver, - .id_table = id_table, - .num_ports = 1, - .set_termios = ir_set_termios, - .attach = ir_startup, - .open = ir_open, - .close = ir_close, - .write = ir_write, - .write_bulk_callback = ir_write_bulk_callback, - .read_bulk_callback = ir_read_bulk_callback, + .description = "IR Dongle", + .usb_driver = &ir_driver, + .id_table = ir_id_table, + .num_ports = 1, + .set_termios = ir_set_termios, + .attach = ir_startup, + .open = ir_open, + .close = ir_close, + .write = ir_write, + .write_bulk_callback = ir_write_bulk_callback, + .read_bulk_callback = ir_read_bulk_callback, }; -static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc) +static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc) { dbg("bLength=%x", desc->bLength); dbg("bDescriptorType=%x", desc->bDescriptorType); - dbg("bcdSpecRevision=%x", desc->bcdSpecRevision); + dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision)); dbg("bmDataSize=%x", desc->bmDataSize); dbg("bmWindowSize=%x", desc->bmWindowSize); dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime); - dbg("wBaudRate=%x", desc->wBaudRate); + dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate)); dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs); dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff); dbg("bMaxUnicastList=%x", desc->bMaxUnicastList); @@ -181,35 +164,37 @@ static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc) * * Based on the same function in drivers/net/irda/irda-usb.c */ -static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum) +static struct usb_irda_cs_descriptor * +irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum) { - struct irda_class_desc *desc; + struct usb_irda_cs_descriptor *desc; int ret; - - desc = kzalloc(sizeof (struct irda_class_desc), GFP_KERNEL); - if (desc == NULL) + + desc = kzalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) return NULL; - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), - IU_REQ_GET_CLASS_DESC, + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_CS_IRDA_GET_CLASS_DESC, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, ifnum, desc, sizeof(*desc), 1000); - + dbg("%s - ret=%d", __func__, ret); if (ret < sizeof(*desc)) { dbg("%s - class descriptor read %s (%d)", __func__, - (ret<0) ? "failed" : "too short", + (ret < 0) ? "failed" : "too short", ret); goto error; } - if (desc->bDescriptorType != USB_DT_IRDA) { + if (desc->bDescriptorType != USB_DT_CS_IRDA) { dbg("%s - bad class descriptor type", __func__); goto error; } - + irda_usb_dump_class_desc(desc); return desc; + error: kfree(desc); return NULL; @@ -219,64 +204,101 @@ error: static u8 ir_xbof_change(u8 xbof) { u8 result; + /* reference irda-usb.c */ - switch(xbof) { - case 48: result = 0x10; break; - case 28: - case 24: result = 0x20; break; - default: - case 12: result = 0x30; break; - case 5: - case 6: result = 0x40; break; - case 3: result = 0x50; break; - case 2: result = 0x60; break; - case 1: result = 0x70; break; - case 0: result = 0x80; break; + switch (xbof) { + case 48: + result = 0x10; + break; + case 28: + case 24: + result = 0x20; + break; + default: + case 12: + result = 0x30; + break; + case 5: + case 6: + result = 0x40; + break; + case 3: + result = 0x50; + break; + case 2: + result = 0x60; + break; + case 1: + result = 0x70; + break; + case 0: + result = 0x80; + break; } + return(result); } -static int ir_startup (struct usb_serial *serial) +static int ir_startup(struct usb_serial *serial) { - struct irda_class_desc *irda_desc; + struct usb_irda_cs_descriptor *irda_desc; - irda_desc = irda_usb_find_class_desc (serial->dev, 0); - if (irda_desc == NULL) { - dev_err (&serial->dev->dev, "IRDA class descriptor not found, device not bound\n"); + irda_desc = irda_usb_find_class_desc(serial->dev, 0); + if (!irda_desc) { + dev_err(&serial->dev->dev, + "IRDA class descriptor not found, device not bound\n"); return -ENODEV; } - dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s", + dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s", __func__, - (irda_desc->wBaudRate & 0x0001) ? " 2400" : "", - (irda_desc->wBaudRate & 0x0002) ? " 9600" : "", - (irda_desc->wBaudRate & 0x0004) ? " 19200" : "", - (irda_desc->wBaudRate & 0x0008) ? " 38400" : "", - (irda_desc->wBaudRate & 0x0010) ? " 57600" : "", - (irda_desc->wBaudRate & 0x0020) ? " 115200" : "", - (irda_desc->wBaudRate & 0x0040) ? " 576000" : "", - (irda_desc->wBaudRate & 0x0080) ? " 1152000" : "", - (irda_desc->wBaudRate & 0x0100) ? " 4000000" : ""); - - switch( irda_desc->bmAdditionalBOFs ) { - case 0x01: ir_add_bof = 48; break; - case 0x02: ir_add_bof = 24; break; - case 0x04: ir_add_bof = 12; break; - case 0x08: ir_add_bof = 6; break; - case 0x10: ir_add_bof = 3; break; - case 0x20: ir_add_bof = 2; break; - case 0x40: ir_add_bof = 1; break; - case 0x80: ir_add_bof = 0; break; - default:; + (irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "", + (irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : ""); + + switch (irda_desc->bmAdditionalBOFs) { + case USB_IRDA_AB_48: + ir_add_bof = 48; + break; + case USB_IRDA_AB_24: + ir_add_bof = 24; + break; + case USB_IRDA_AB_12: + ir_add_bof = 12; + break; + case USB_IRDA_AB_6: + ir_add_bof = 6; + break; + case USB_IRDA_AB_3: + ir_add_bof = 3; + break; + case USB_IRDA_AB_2: + ir_add_bof = 2; + break; + case USB_IRDA_AB_1: + ir_add_bof = 1; + break; + case USB_IRDA_AB_0: + ir_add_bof = 0; + break; + default: + break; } - kfree (irda_desc); + kfree(irda_desc); - return 0; + return 0; } -static int ir_open (struct usb_serial_port *port, struct file *filp) +static int ir_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { char *buffer; int result = 0; @@ -285,51 +307,56 @@ static int ir_open (struct usb_serial_port *port, struct file *filp) if (buffer_size) { /* override the default buffer sizes */ - buffer = kmalloc (buffer_size, GFP_KERNEL); + buffer = kmalloc(buffer_size, GFP_KERNEL); if (!buffer) { - dev_err (&port->dev, "%s - out of memory.\n", __func__); + dev_err(&port->dev, "%s - out of memory.\n", __func__); return -ENOMEM; } - kfree (port->read_urb->transfer_buffer); + kfree(port->read_urb->transfer_buffer); port->read_urb->transfer_buffer = buffer; port->read_urb->transfer_buffer_length = buffer_size; - buffer = kmalloc (buffer_size, GFP_KERNEL); + buffer = kmalloc(buffer_size, GFP_KERNEL); if (!buffer) { - dev_err (&port->dev, "%s - out of memory.\n", __func__); + dev_err(&port->dev, "%s - out of memory.\n", __func__); return -ENOMEM; } - kfree (port->write_urb->transfer_buffer); + kfree(port->write_urb->transfer_buffer); port->write_urb->transfer_buffer = buffer; port->write_urb->transfer_buffer_length = buffer_size; port->bulk_out_size = buffer_size; } /* Start reading from the device */ - usb_fill_bulk_urb ( + usb_fill_bulk_urb( port->read_urb, - port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), + port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, ir_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) - dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); return result; } -static void ir_close (struct usb_serial_port *port, struct file * filp) +static void ir_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file * filp) { dbg("%s - port %d", __func__, port->number); - + /* shutdown our bulk read */ usb_kill_urb(port->read_urb); } -static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count) +static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { unsigned char *transfer_buffer; int result; @@ -337,11 +364,6 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int dbg("%s - port = %d, count = %d", __func__, port->number, count); - if (!port->tty) { - dev_err (&port->dev, "%s - no tty???\n", __func__); - return 0; - } - if (count == 0) return 0; @@ -359,7 +381,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int /* * The first byte of the packet we send to the device contains an - * inband header which indicates an additional number of BOFs and + * inbound header which indicates an additional number of BOFs and * a baud rate change. * * See section 5.4.2.2 of the USB IrDA spec. @@ -367,9 +389,9 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int *transfer_buffer = ir_xbof | ir_baud; ++transfer_buffer; - memcpy (transfer_buffer, buf, transfer_size); + memcpy(transfer_buffer, buf, transfer_size); - usb_fill_bulk_urb ( + usb_fill_bulk_urb( port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, @@ -381,17 +403,19 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int port->write_urb->transfer_flags = URB_ZERO_PACKET; - result = usb_submit_urb (port->write_urb, GFP_ATOMIC); + result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { port->write_urb_busy = 0; - dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); } else result = transfer_size; return result; } -static void ir_write_bulk_callback (struct urb *urb) +static void ir_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; int status = urb->status; @@ -405,7 +429,7 @@ static void ir_write_bulk_callback (struct urb *urb) return; } - usb_serial_debug_data ( + usb_serial_debug_data( debug, &port->dev, __func__, @@ -415,7 +439,7 @@ static void ir_write_bulk_callback (struct urb *urb) usb_serial_port_softint(port); } -static void ir_read_bulk_callback (struct urb *urb) +static void ir_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct tty_struct *tty; @@ -425,74 +449,61 @@ static void ir_read_bulk_callback (struct urb *urb) dbg("%s - port %d", __func__, port->number); - if (!port->open_count) { + if (!port->port.count) { dbg("%s - port closed.", __func__); return; } switch (status) { - case 0: /* Successful */ - - /* - * The first byte of the packet we get from the device - * contains a busy indicator and baud rate change. - * See section 5.4.1.2 of the USB IrDA spec. - */ - if ((*data & 0x0f) > 0) - ir_baud = *data & 0x0f; - - usb_serial_debug_data ( - debug, - &port->dev, - __func__, - urb->actual_length, - data); - - tty = port->tty; - - if (tty_buffer_request_room(tty, urb->actual_length - 1)) { - tty_insert_flip_string(tty, data+1, urb->actual_length - 1); - tty_flip_buffer_push(tty); - } - - /* - * No break here. - * We want to resubmit the urb so we can read - * again. - */ + case 0: /* Successful */ + /* + * The first byte of the packet we get from the device + * contains a busy indicator and baud rate change. + * See section 5.4.1.2 of the USB IrDA spec. + */ + if ((*data & 0x0f) > 0) + ir_baud = *data & 0x0f; + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); + tty = port->port.tty; + if (tty_buffer_request_room(tty, urb->actual_length - 1)) { + tty_insert_flip_string(tty, data+1, urb->actual_length - 1); + tty_flip_buffer_push(tty); + } - case -EPROTO: /* taking inspiration from pl2303.c */ + /* + * No break here. + * We want to resubmit the urb so we can read + * again. + */ + case -EPROTO: /* taking inspiration from pl2303.c */ /* Continue trying to always read */ - usb_fill_bulk_urb ( - port->read_urb, - port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - ir_read_bulk_callback, - port); - - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", - __func__, result); - - break ; - - default: - dbg("%s - nonzero read bulk status received: %d", - __func__, - status); + usb_fill_bulk_urb( + port->read_urb, + port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ir_read_bulk_callback, + port); + + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", + __func__, result); break ; - + default: + dbg("%s - nonzero read bulk status received: %d", + __func__, status); + break ; } - return; } -static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) +static void ir_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { unsigned char *transfer_buffer; int result; @@ -501,7 +512,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t dbg("%s - port %d", __func__, port->number); - baud = tty_get_baud_rate(port->tty); + baud = tty_get_baud_rate(tty); /* * FIXME, we should compare the baud request against the @@ -510,19 +521,36 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t */ switch (baud) { - case 2400: ir_baud = SPEED_2400; break; - case 9600: ir_baud = SPEED_9600; break; - case 19200: ir_baud = SPEED_19200; break; - case 38400: ir_baud = SPEED_38400; break; - case 57600: ir_baud = SPEED_57600; break; - case 115200: ir_baud = SPEED_115200; break; - case 576000: ir_baud = SPEED_576000; break; - case 1152000: ir_baud = SPEED_1152000; break; - case 4000000: ir_baud = SPEED_4000000; break; - break; - default: - ir_baud = SPEED_9600; - baud = 9600; + case 2400: + ir_baud = USB_IRDA_BR_2400; + break; + case 9600: + ir_baud = USB_IRDA_BR_9600; + break; + case 19200: + ir_baud = USB_IRDA_BR_19200; + break; + case 38400: + ir_baud = USB_IRDA_BR_38400; + break; + case 57600: + ir_baud = USB_IRDA_BR_57600; + break; + case 115200: + ir_baud = USB_IRDA_BR_115200; + break; + case 576000: + ir_baud = USB_IRDA_BR_576000; + break; + case 1152000: + ir_baud = USB_IRDA_BR_1152000; + break; + case 4000000: + ir_baud = USB_IRDA_BR_4000000; + break; + default: + ir_baud = USB_IRDA_BR_9600; + baud = 9600; } if (xbof == -1) @@ -538,10 +566,11 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t transfer_buffer = port->write_urb->transfer_buffer; *transfer_buffer = ir_xbof | ir_baud; - usb_fill_bulk_urb ( + usb_fill_bulk_urb( port->write_urb, port->serial->dev, - usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), + usb_sndbulkpipe(port->serial->dev, + port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, 1, ir_write_bulk_callback, @@ -549,38 +578,44 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t port->write_urb->transfer_flags = URB_ZERO_PACKET; - result = usb_submit_urb (port->write_urb, GFP_KERNEL); + result = usb_submit_urb(port->write_urb, GFP_KERNEL); if (result) - dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); /* Only speed changes are supported */ - tty_termios_copy_hw(port->tty->termios, old_termios); - tty_encode_baud_rate(port->tty, baud, baud); + tty_termios_copy_hw(tty->termios, old_termios); + tty_encode_baud_rate(tty, baud, baud); } - -static int __init ir_init (void) +static int __init ir_init(void) { int retval; + retval = usb_serial_register(&ir_device); if (retval) goto failed_usb_serial_register; + retval = usb_register(&ir_driver); - if (retval) + if (retval) goto failed_usb_register; + info(DRIVER_DESC " " DRIVER_VERSION); + return 0; + failed_usb_register: usb_serial_deregister(&ir_device); + failed_usb_serial_register: return retval; } - -static void __exit ir_exit (void) +static void __exit ir_exit(void) { - usb_deregister (&ir_driver); - usb_serial_deregister (&ir_device); + usb_deregister(&ir_driver); + usb_serial_deregister(&ir_device); } diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index a01e987c7d32..ddff37fa6339 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -144,9 +144,10 @@ static void iuu_shutdown(struct usb_serial *serial) } } -static int iuu_tiocmset(struct usb_serial_port *port, struct file *file, +static int iuu_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct iuu_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -171,8 +172,9 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file, * When no card , the reader respond with TIOCM_CD * This is known as CD autodetect mechanism */ -static int iuu_tiocmget(struct usb_serial_port *port, struct file *file) +static int iuu_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct iuu_private *priv = usb_get_serial_port_data(port); unsigned long flags; int rc; @@ -316,11 +318,10 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count) port->bulk_out_endpointAddress), buf, count, &actual, HZ * 1); - if (status != IUU_OPERATION_OK) { + if (status != IUU_OPERATION_OK) dbg("%s - error = %2x", __func__, status); - } else { + else dbg("%s - write OK !", __func__); - } return status; } @@ -340,12 +341,10 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count) port->bulk_in_endpointAddress), buf, count, &actual, HZ * 1); - if (status != IUU_OPERATION_OK) { + if (status != IUU_OPERATION_OK) dbg("%s - error = %2x", __func__, status); - } else { + else dbg("%s - read OK !", __func__); - } - return status; } @@ -630,7 +629,7 @@ static void read_buf_callback(struct urb *urb) } dbg("%s - %i chars to write", __func__, urb->actual_length); - tty = port->tty; + tty = port->port.tty; if (data == NULL) dbg("%s - data is NULL !!!", __func__); if (tty && urb->actual_length && data) { @@ -752,11 +751,10 @@ static void iuu_uart_read_callback(struct urb *urb) /* if nothing to write call again rxcmd */ dbg("%s - rxcmd recall", __func__); iuu_led_activity_off(urb); - return; } -static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf, - int count) +static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, + const u8 *buf, int count) { struct iuu_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -769,14 +767,14 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf, if (priv->writelen > 0) { /* buffer already filled but not commited */ spin_unlock_irqrestore(&priv->lock, flags); - return (0); + return 0; } /* fill the buffer */ memcpy(priv->writebuf, buf, count); priv->writelen = count; spin_unlock_irqrestore(&priv->lock, flags); - return (count); + return count; } static void read_rxcmd_callback(struct urb *urb) @@ -948,7 +946,8 @@ static int set_control_lines(struct usb_device *dev, u8 value) return 0; } -static void iuu_close(struct usb_serial_port *port, struct file *filp) +static void iuu_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { /* iuu_led (port,255,0,0,0); */ struct usb_serial *serial; @@ -964,8 +963,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp) iuu_uart_off(port); if (serial->dev) { - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; + if (tty) { + c_cflag = tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop DTR and RTS */ priv = usb_get_serial_port_data(port); @@ -989,7 +988,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp) } } -static int iuu_open(struct usb_serial_port *port, struct file *filp) +static int iuu_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; u8 *buf; @@ -1036,15 +1036,17 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) /* set the termios structure */ spin_lock_irqsave(&priv->lock, flags); - if (!priv->termios_initialized) { - *(port->tty->termios) = tty_std_termios; - port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 - | TIOCM_CTS | CSTOPB | PARENB; - port->tty->termios->c_lflag = 0; - port->tty->termios->c_oflag = 0; - port->tty->termios->c_iflag = 0; + if (tty && !priv->termios_initialized) { + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 + | TIOCM_CTS | CSTOPB | PARENB; + tty->termios->c_ispeed = 9600; + tty->termios->c_ospeed = 9600; + tty->termios->c_lflag = 0; + tty->termios->c_oflag = 0; + tty->termios->c_iflag = 0; priv->termios_initialized = 1; - port->tty->low_latency = 1; + tty->low_latency = 1; priv->poll = 0; } spin_unlock_irqrestore(&priv->lock, flags); @@ -1148,7 +1150,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) if (result) { dev_err(&port->dev, "%s - failed submitting read urb," " error %d\n", __func__, result); - iuu_close(port, NULL); + iuu_close(tty, port, NULL); return -EPROTO; } else { dbg("%s - rxcmd OK", __func__); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 11e439b90eac..704716f6f6d3 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1,29 +1,29 @@ /* Keyspan USB to Serial Converter driver - + (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org> (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com> - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See http://misc.nu/hugh/keyspan.html for more information. - + Code in this driver inspired by and in a number of places taken from Brian Warner's original Keyspan-PDA driver. This driver has been put together with the support of Innosys, Inc. and Keyspan, Inc the manufacturers of the Keyspan USB-serial products. Thanks Guys :) - + Thanks to Paulus for miscellaneous tidy ups, some largish chunks of much nicer and/or completely new code and (perhaps most uniquely) having the patience to sit down and explain why and where he'd changed - stuff. - - Tip 'o the hat to IBM (and previously Linuxcare :) for supporting + stuff. + + Tip 'o the hat to IBM (and previously Linuxcare :) for supporting staff in their work on open source projects. Change History @@ -70,21 +70,21 @@ Thu May 31 11:56:42 PDT 2001 gkh switched from using spinlock to a semaphore - + (04/08/2001) gb Identify version on module load. - + (11/01/2000) Adam J. Richter usb_device_id table support. - + Tue Oct 10 23:15:33 EST 2000 Hugh Merged Paul's changes with my USA-49W mods. Work in progress still... - + Wed Jul 19 14:00:42 EST 2000 gkh Added module_init and module_exit functions to handle the fact that this driver is a loadable module now. - + Tue Jul 18 16:14:52 EST 2000 Hugh Basic character input/output for USA-19 now mostly works, fixed at 9600 baud for the moment. @@ -107,7 +107,7 @@ #include <linux/spinlock.h> #include <linux/firmware.h> #include <linux/ihex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "keyspan.h" @@ -132,15 +132,15 @@ struct keyspan_serial_private { struct urb *instat_urb; char instat_buf[INSTAT_BUFLEN]; - /* added to support 49wg, where data from all 4 ports comes in on 1 EP */ - /* and high-speed supported */ + /* added to support 49wg, where data from all 4 ports comes in + on 1 EP and high-speed supported */ struct urb *indat_urb; char indat_buf[INDAT49W_BUFLEN]; /* XXX this one probably will need a lock */ struct urb *glocont_urb; char glocont_buf[GLOCONT_BUFLEN]; - char ctrl_buf[8]; // for EP0 control message + char ctrl_buf[8]; /* for EP0 control message */ }; struct keyspan_port_private { @@ -186,19 +186,19 @@ struct keyspan_port_private { int resend_cont; /* need to resend control packet */ }; - /* Include Keyspan message headers. All current Keyspan Adapters make use of one of five message formats which are referred - to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */ + to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and + within this driver. */ #include "keyspan_usa26msg.h" #include "keyspan_usa28msg.h" #include "keyspan_usa49msg.h" #include "keyspan_usa90msg.h" #include "keyspan_usa67msg.h" - + /* Functions used by new usb-serial code. */ -static int __init keyspan_init (void) +static int __init keyspan_init(void) { int retval; retval = usb_serial_register(&keyspan_pre_device); @@ -214,7 +214,7 @@ static int __init keyspan_init (void) if (retval) goto failed_4port_device_register; retval = usb_register(&keyspan_driver); - if (retval) + if (retval) goto failed_usb_register; info(DRIVER_VERSION ":" DRIVER_DESC); @@ -232,35 +232,24 @@ failed_pre_device_register: return retval; } -static void __exit keyspan_exit (void) +static void __exit keyspan_exit(void) { - usb_deregister (&keyspan_driver); - usb_serial_deregister (&keyspan_pre_device); - usb_serial_deregister (&keyspan_1port_device); - usb_serial_deregister (&keyspan_2port_device); - usb_serial_deregister (&keyspan_4port_device); + usb_deregister(&keyspan_driver); + usb_serial_deregister(&keyspan_pre_device); + usb_serial_deregister(&keyspan_1port_device); + usb_serial_deregister(&keyspan_2port_device); + usb_serial_deregister(&keyspan_4port_device); } module_init(keyspan_init); module_exit(keyspan_exit); -static void keyspan_rx_throttle (struct usb_serial_port *port) -{ - dbg("%s - port %d", __func__, port->number); -} - - -static void keyspan_rx_unthrottle (struct usb_serial_port *port) -{ - dbg("%s - port %d", __func__, port->number); -} - - -static void keyspan_break_ctl (struct usb_serial_port *port, int break_state) +static void keyspan_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct keyspan_port_private *p_priv; - dbg("%s", __func__); + dbg("%s", __func__); p_priv = usb_get_serial_port_data(port); @@ -273,14 +262,13 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state) } -static void keyspan_set_termios (struct usb_serial_port *port, - struct ktermios *old_termios) +static void keyspan_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { int baud_rate, device_port; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; unsigned int cflag; - struct tty_struct *tty = port->tty; dbg("%s", __func__); @@ -292,7 +280,7 @@ static void keyspan_set_termios (struct usb_serial_port *port, /* Baud rate calculation takes baud rate as an integer so other rates can be generated if desired. */ baud_rate = tty_get_baud_rate(tty); - /* If no match or invalid, don't change */ + /* If no match or invalid, don't change */ if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { /* FIXME - more to do here to ensure rate changes cleanly */ @@ -312,35 +300,32 @@ static void keyspan_set_termios (struct usb_serial_port *port, keyspan_send_setup(port, 0); } -static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file) +static int keyspan_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; + struct keyspan_port_private *p_priv = usb_get_serial_port_data(port); unsigned int value; - struct keyspan_port_private *p_priv; - p_priv = usb_get_serial_port_data(port); - value = ((p_priv->rts_state) ? TIOCM_RTS : 0) | ((p_priv->dtr_state) ? TIOCM_DTR : 0) | ((p_priv->cts_state) ? TIOCM_CTS : 0) | ((p_priv->dsr_state) ? TIOCM_DSR : 0) | ((p_priv->dcd_state) ? TIOCM_CAR : 0) | - ((p_priv->ri_state) ? TIOCM_RNG : 0); + ((p_priv->ri_state) ? TIOCM_RNG : 0); return value; } -static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file, +static int keyspan_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - struct keyspan_port_private *p_priv; + struct usb_serial_port *port = tty->driver_data; + struct keyspan_port_private *p_priv = usb_get_serial_port_data(port); - p_priv = usb_get_serial_port_data(port); - if (set & TIOCM_RTS) p_priv->rts_state = 1; if (set & TIOCM_DTR) p_priv->dtr_state = 1; - if (clear & TIOCM_RTS) p_priv->rts_state = 0; if (clear & TIOCM_DTR) @@ -349,35 +334,29 @@ static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file, return 0; } -static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; -} - - /* Write function is similar for the four protocols used - with only a minor change for usa90 (usa19hs) required */ -static int keyspan_write(struct usb_serial_port *port, - const unsigned char *buf, int count) +/* Write function is similar for the four protocols used + with only a minor change for usa90 (usa19hs) required */ +static int keyspan_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count) { struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; int flip; int left, todo; struct urb *this_urb; - int err, maxDataLen, dataOffset; + int err, maxDataLen, dataOffset; p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; if (d_details->msg_format == msg_usa90) { - maxDataLen = 64; + maxDataLen = 64; dataOffset = 0; } else { maxDataLen = 63; dataOffset = 1; } - + dbg("%s - for port %d (%d chars), flip=%d", __func__, port->number, count, p_priv->out_flip); @@ -387,37 +366,40 @@ static int keyspan_write(struct usb_serial_port *port, todo = maxDataLen; flip = p_priv->out_flip; - + /* Check we have a valid urb/endpoint before we use it... */ - if ((this_urb = p_priv->out_urbs[flip]) == NULL) { + this_urb = p_priv->out_urbs[flip]; + if (this_urb == NULL) { /* no bulk out, so return 0 bytes written */ dbg("%s - no output urb :(", __func__); return count; } - dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip); + dbg("%s - endpoint %d flip %d", + __func__, usb_pipeendpoint(this_urb->pipe), flip); if (this_urb->status == -EINPROGRESS) { - if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ)) + if (time_before(jiffies, + p_priv->tx_start_time[flip] + 10 * HZ)) break; usb_unlink_urb(this_urb); break; } - /* First byte in buffer is "last flag" (except for usa19hx) - unused so - for now so set to zero */ + /* First byte in buffer is "last flag" (except for usa19hx) + - unused so for now so set to zero */ ((char *)this_urb->transfer_buffer)[0] = 0; - memcpy (this_urb->transfer_buffer + dataOffset, buf, todo); + memcpy(this_urb->transfer_buffer + dataOffset, buf, todo); buf += todo; /* send the data out the bulk port */ this_urb->transfer_buffer_length = todo + dataOffset; this_urb->dev = port->serial->dev; - if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(this_urb, GFP_ATOMIC); + if (err != 0) dbg("usb_submit_urb(write bulk) failed (%d)", err); - } p_priv->tx_start_time[flip] = jiffies; /* Flip for next time if usa26 or usa28 interface @@ -437,7 +419,7 @@ static void usa26_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); endpoint = usb_pipeendpoint(urb->pipe); @@ -448,17 +430,18 @@ static void usa26_indat_callback(struct urb *urb) } port = urb->context; - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { - /* no errors on individual bytes, only possible overrun err*/ + /* no errors on individual bytes, only + possible overrun err */ if (data[0] & RXERROR_OVERRUN) - err = TTY_OVERRUN; - else err = 0; - for (i = 1; i < urb->actual_length ; ++i) { + err = TTY_OVERRUN; + else + err = 0; + for (i = 1; i < urb->actual_length ; ++i) tty_insert_flip_char(tty, data[i], err); - } } else { /* some bytes had errors, every byte has status */ dbg("%s - RX error!!!!", __func__); @@ -476,17 +459,19 @@ static void usa26_indat_callback(struct urb *urb) } tty_flip_buffer_push(tty); } - - /* Resubmit urb so we continue receiving */ + + /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->open_count) - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } + if (port->port.count) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", + __func__, err); + } return; } - /* Outdat handling is common for all devices */ +/* Outdat handling is common for all devices */ static void usa2x_outdat_callback(struct urb *urb) { struct usb_serial_port *port; @@ -494,16 +479,16 @@ static void usa2x_outdat_callback(struct urb *urb) port = urb->context; p_priv = usb_get_serial_port_data(port); - dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]); + dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]); - if (port->open_count) + if (port->port.count) usb_serial_port_softint(port); } static void usa26_inack_callback(struct urb *urb) { - dbg ("%s", __func__); - + dbg("%s", __func__); + } static void usa26_outcont_callback(struct urb *urb) @@ -515,8 +500,9 @@ static void usa26_outcont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg ("%s - sending setup", __func__); - keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1); + dbg("%s - sending setup", __func__); + keyspan_usa26_send_setup(port->serial, port, + p_priv->resend_cont - 1); } } @@ -552,14 +538,14 @@ static void usa26_instat_callback(struct urb *urb) /* Now do something useful with the data */ - /* Check port number from message and retrieve private data */ + /* Check port number from message and retrieve private data */ if (msg->port >= serial->num_ports) { - dbg ("%s - Unexpected port number %d", __func__, msg->port); + dbg("%s - Unexpected port number %d", __func__, msg->port); goto exit; } port = serial->port[msg->port]; p_priv = usb_get_serial_port_data(port); - + /* Update handshaking pin state information */ old_dcd_state = p_priv->dcd_state; p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); @@ -567,39 +553,38 @@ static void usa26_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->tty && !C_CLOCAL(port->tty) + if (port->port.tty && !C_CLOCAL(port->port.tty) && old_dcd_state != p_priv->dcd_state) { if (old_dcd_state) - tty_hangup(port->tty); + tty_hangup(port->port.tty); /* else */ /* wake_up_interruptible(&p_priv->open_wait); */ } - + /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } exit: ; } static void usa26_glocont_callback(struct urb *urb) { - dbg ("%s", __func__); - + dbg("%s", __func__); } static void usa28_indat_callback(struct urb *urb) { - int i, err; + int err; struct usb_serial_port *port; struct tty_struct *tty; unsigned char *data; struct keyspan_port_private *p_priv; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); port = urb->context; p_priv = usb_get_serial_port_data(port); @@ -619,20 +604,20 @@ static void usa28_indat_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); data = urb->transfer_buffer; - tty = port->tty; + tty = port->port.tty; if (urb->actual_length) { - for (i = 0; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } + tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->open_count) - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } + if (port->port.count) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", + __func__, err); + } p_priv->in_flip ^= 1; urb = p_priv->in_urbs[p_priv->in_flip]; @@ -641,7 +626,7 @@ static void usa28_indat_callback(struct urb *urb) static void usa28_inack_callback(struct urb *urb) { - dbg ("%s", __func__); + dbg("%s", __func__); } static void usa28_outcont_callback(struct urb *urb) @@ -653,8 +638,9 @@ static void usa28_outcont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg ("%s - sending setup", __func__); - keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1); + dbg("%s - sending setup", __func__); + keyspan_usa28_send_setup(port->serial, port, + p_priv->resend_cont - 1); } } @@ -684,19 +670,18 @@ static void usa28_instat_callback(struct urb *urb) /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]);*/ - - /* Now do something useful with the data */ - msg = (struct keyspan_usa28_portStatusMessage *)data; + /* Now do something useful with the data */ + msg = (struct keyspan_usa28_portStatusMessage *)data; - /* Check port number from message and retrieve private data */ + /* Check port number from message and retrieve private data */ if (msg->port >= serial->num_ports) { - dbg ("%s - Unexpected port number %d", __func__, msg->port); + dbg("%s - Unexpected port number %d", __func__, msg->port); goto exit; } port = serial->port[msg->port]; p_priv = usb_get_serial_port_data(port); - + /* Update handshaking pin state information */ old_dcd_state = p_priv->dcd_state; p_priv->cts_state = ((msg->cts) ? 1 : 0); @@ -704,25 +689,25 @@ static void usa28_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->tty && !C_CLOCAL(port->tty) + if (port->port.tty && !C_CLOCAL(port->port.tty) && old_dcd_state != p_priv->dcd_state) { if (old_dcd_state) - tty_hangup(port->tty); + tty_hangup(port->port.tty); /* else */ /* wake_up_interruptible(&p_priv->open_wait); */ } /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } exit: ; } static void usa28_glocont_callback(struct urb *urb) { - dbg ("%s", __func__); + dbg("%s", __func__); } @@ -733,7 +718,7 @@ static void usa49_glocont_callback(struct urb *urb) struct keyspan_port_private *p_priv; int i; - dbg ("%s", __func__); + dbg("%s", __func__); serial = urb->context; for (i = 0; i < serial->num_ports; ++i) { @@ -741,8 +726,9 @@ static void usa49_glocont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg ("%s - sending setup", __func__); - keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1); + dbg("%s - sending setup", __func__); + keyspan_usa49_send_setup(serial, port, + p_priv->resend_cont - 1); break; } } @@ -761,7 +747,7 @@ static void usa49_instat_callback(struct urb *urb) int old_dcd_state; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); serial = urb->context; @@ -770,7 +756,8 @@ static void usa49_instat_callback(struct urb *urb) return; } - if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) { + if (urb->actual_length != + sizeof(struct keyspan_usa49_portStatusMessage)) { dbg("%s - bad length %d", __func__, urb->actual_length); goto exit; } @@ -778,18 +765,19 @@ static void usa49_instat_callback(struct urb *urb) /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10]);*/ - - /* Now do something useful with the data */ + + /* Now do something useful with the data */ msg = (struct keyspan_usa49_portStatusMessage *)data; - /* Check port number from message and retrieve private data */ + /* Check port number from message and retrieve private data */ if (msg->portNumber >= serial->num_ports) { - dbg ("%s - Unexpected port number %d", __func__, msg->portNumber); + dbg("%s - Unexpected port number %d", + __func__, msg->portNumber); goto exit; } port = serial->port[msg->portNumber]; p_priv = usb_get_serial_port_data(port); - + /* Update handshaking pin state information */ old_dcd_state = p_priv->dcd_state; p_priv->cts_state = ((msg->cts) ? 1 : 0); @@ -797,26 +785,26 @@ static void usa49_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->tty && !C_CLOCAL(port->tty) + if (port->port.tty && !C_CLOCAL(port->port.tty) && old_dcd_state != p_priv->dcd_state) { if (old_dcd_state) - tty_hangup(port->tty); + tty_hangup(port->port.tty); /* else */ /* wake_up_interruptible(&p_priv->open_wait); */ } - /* Resubmit urb so we continue receiving */ + /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } exit: ; } static void usa49_inack_callback(struct urb *urb) { - dbg ("%s", __func__); + dbg("%s", __func__); } static void usa49_indat_callback(struct urb *urb) @@ -828,7 +816,7 @@ static void usa49_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); endpoint = usb_pipeendpoint(urb->pipe); @@ -839,14 +827,13 @@ static void usa49_indat_callback(struct urb *urb) } port = urb->context; - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { /* no error on any byte */ - for (i = 1; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } + tty_insert_flip_string(tty, data + 1, + urb->actual_length - 1); } else { /* some bytes had errors, every byte has status */ for (i = 0; i + 1 < urb->actual_length; i += 2) { @@ -863,13 +850,15 @@ static void usa49_indat_callback(struct urb *urb) } tty_flip_buffer_push(tty); } - - /* Resubmit urb so we continue receiving */ + + /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->open_count) - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } + if (port->port.count) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", + __func__, err); + } } static void usa49wg_indat_callback(struct urb *urb) @@ -881,7 +870,7 @@ static void usa49wg_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); serial = urb->context; @@ -899,12 +888,12 @@ static void usa49wg_indat_callback(struct urb *urb) /* Check port number from message*/ if (data[i] >= serial->num_ports) { - dbg ("%s - Unexpected port number %d", + dbg("%s - Unexpected port number %d", __func__, data[i]); return; } port = serial->port[data[i++]]; - tty = port->tty; + tty = port->port.tty; len = data[i++]; /* 0x80 bit is error flag */ @@ -912,7 +901,7 @@ static void usa49wg_indat_callback(struct urb *urb) /* no error on any byte */ i++; for (x = 1; x < len ; ++x) - if (port->open_count) + if (port->port.count) tty_insert_flip_char(tty, data[i++], 0); else @@ -930,13 +919,13 @@ static void usa49wg_indat_callback(struct urb *urb) if (stat & RXERROR_PARITY) flag |= TTY_PARITY; /* XXX should handle break (0x10) */ - if (port->open_count) + if (port->port.count) tty_insert_flip_char(tty, data[i+1], flag); i += 2; } } - if (port->open_count) + if (port->port.count) tty_flip_buffer_push(tty); } } @@ -952,7 +941,7 @@ static void usa49wg_indat_callback(struct urb *urb) /* not used, usa-49 doesn't have per-port control endpoints */ static void usa49_outcont_callback(struct urb *urb) { - dbg ("%s", __func__); + dbg("%s", __func__); } static void usa90_indat_callback(struct urb *urb) @@ -965,7 +954,7 @@ static void usa90_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); endpoint = usb_pipeendpoint(urb->pipe); @@ -978,29 +967,26 @@ static void usa90_indat_callback(struct urb *urb) port = urb->context; p_priv = usb_get_serial_port_data(port); - tty = port->tty; + tty = port->port.tty; if (urb->actual_length) { - /* if current mode is DMA, looks like usa28 format - otherwise looks like usa26 data format */ + otherwise looks like usa26 data format */ - if (p_priv->baud > 57600) { - for (i = 0; i < urb->actual_length ; ++i) - tty_insert_flip_char(tty, data[i], 0); - } + if (p_priv->baud > 57600) + tty_insert_flip_string(tty, data, urb->actual_length); else { - /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { - /* no errors on individual bytes, only possible overrun err*/ + /* no errors on individual bytes, only + possible overrun err*/ if (data[0] & RXERROR_OVERRUN) - err = TTY_OVERRUN; - else err = 0; - for (i = 1; i < urb->actual_length ; ++i) - tty_insert_flip_char(tty, data[i], err); - - } - else { + err = TTY_OVERRUN; + else + err = 0; + for (i = 1; i < urb->actual_length ; ++i) + tty_insert_flip_char(tty, data[i], + err); + } else { /* some bytes had errors, every byte has status */ dbg("%s - RX error!!!!", __func__); for (i = 0; i + 1 < urb->actual_length; i += 2) { @@ -1012,19 +998,22 @@ static void usa90_indat_callback(struct urb *urb) if (stat & RXERROR_PARITY) flag |= TTY_PARITY; /* XXX should handle break (0x10) */ - tty_insert_flip_char(tty, data[i+1], flag); + tty_insert_flip_char(tty, data[i+1], + flag); } } } tty_flip_buffer_push(tty); } - + /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->open_count) - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } + if (port->port.count) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", + __func__, err); + } return; } @@ -1056,7 +1045,7 @@ static void usa90_instat_callback(struct urb *urb) port = serial->port[0]; p_priv = usb_get_serial_port_data(port); - + /* Update handshaking pin state information */ old_dcd_state = p_priv->dcd_state; p_priv->cts_state = ((msg->cts) ? 1 : 0); @@ -1064,19 +1053,19 @@ static void usa90_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->tty && !C_CLOCAL(port->tty) + if (port->port.tty && !C_CLOCAL(port->port.tty) && old_dcd_state != p_priv->dcd_state) { if (old_dcd_state) - tty_hangup(port->tty); + tty_hangup(port->port.tty); /* else */ /* wake_up_interruptible(&p_priv->open_wait); */ } - + /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) dbg("%s - resubmit read urb failed. (%d)", __func__, err); - } exit: ; } @@ -1090,8 +1079,9 @@ static void usa90_outcont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg ("%s - sending setup", __func__); - keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1); + dbg("%s - sending setup", __func__); + keyspan_usa90_send_setup(port->serial, port, + p_priv->resend_cont - 1); } } @@ -1107,7 +1097,7 @@ static void usa67_instat_callback(struct urb *urb) int old_dcd_state; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); serial = urb->context; @@ -1116,7 +1106,8 @@ static void usa67_instat_callback(struct urb *urb) return; } - if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) { + if (urb->actual_length != + sizeof(struct keyspan_usa67_portStatusMessage)) { dbg("%s - bad length %d", __func__, urb->actual_length); return; } @@ -1127,7 +1118,7 @@ static void usa67_instat_callback(struct urb *urb) /* Check port number from message and retrieve private data */ if (msg->port >= serial->num_ports) { - dbg ("%s - Unexpected port number %d", __func__, msg->port); + dbg("%s - Unexpected port number %d", __func__, msg->port); return; } @@ -1139,10 +1130,10 @@ static void usa67_instat_callback(struct urb *urb) p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); - if (port->tty && !C_CLOCAL(port->tty) + if (port->port.tty && !C_CLOCAL(port->port.tty) && old_dcd_state != p_priv->dcd_state) { if (old_dcd_state) - tty_hangup(port->tty); + tty_hangup(port->port.tty); /* else */ /* wake_up_interruptible(&p_priv->open_wait); */ } @@ -1161,7 +1152,7 @@ static void usa67_glocont_callback(struct urb *urb) struct keyspan_port_private *p_priv; int i; - dbg ("%s", __func__); + dbg("%s", __func__); serial = urb->context; for (i = 0; i < serial->num_ports; ++i) { @@ -1169,7 +1160,7 @@ static void usa67_glocont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg ("%s - sending setup", __func__); + dbg("%s - sending setup", __func__); keyspan_usa67_send_setup(serial, port, p_priv->resend_cont - 1); break; @@ -1177,8 +1168,9 @@ static void usa67_glocont_callback(struct urb *urb) } } -static int keyspan_write_room (struct usb_serial_port *port) +static int keyspan_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; int flip; @@ -1191,32 +1183,30 @@ static int keyspan_write_room (struct usb_serial_port *port) /* FIXME: locking */ if (d_details->msg_format == msg_usa90) - data_len = 64; + data_len = 64; else data_len = 63; flip = p_priv->out_flip; /* Check both endpoints to see if any are available. */ - if ((this_urb = p_priv->out_urbs[flip]) != NULL) { + this_urb = p_priv->out_urbs[flip]; + if (this_urb != NULL) { if (this_urb->status != -EINPROGRESS) - return (data_len); - flip = (flip + 1) & d_details->outdat_endp_flip; - if ((this_urb = p_priv->out_urbs[flip]) != NULL) + return data_len; + flip = (flip + 1) & d_details->outdat_endp_flip; + this_urb = p_priv->out_urbs[flip]; + if (this_urb != NULL) { if (this_urb->status != -EINPROGRESS) - return (data_len); + return data_len; + } } return 0; } -static int keyspan_chars_in_buffer (struct usb_serial_port *port) -{ - return 0; -} - - -static int keyspan_open (struct usb_serial_port *port, struct file *filp) +static int keyspan_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct keyspan_port_private *p_priv; struct keyspan_serial_private *s_priv; @@ -1225,7 +1215,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) int i, err; int baud_rate, device_port; struct urb *urb; - unsigned int cflag; + unsigned int cflag = 0; s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); @@ -1247,50 +1237,53 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) /* Reset low level data toggle and start reading from endpoints */ for (i = 0; i < 2; i++) { - if ((urb = p_priv->in_urbs[i]) == NULL) + urb = p_priv->in_urbs[i]; + if (urb == NULL) continue; urb->dev = serial->dev; - /* make sure endpoint data toggle is synchronized with the device */ - + /* make sure endpoint data toggle is synchronized + with the device */ usb_clear_halt(urb->dev, urb->pipe); - - if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { - dbg("%s - submit urb %d failed (%d)", __func__, i, err); - } + err = usb_submit_urb(urb, GFP_KERNEL); + if (err != 0) + dbg("%s - submit urb %d failed (%d)", + __func__, i, err); } /* Reset low level data toggle on out endpoints */ for (i = 0; i < 2; i++) { - if ((urb = p_priv->out_urbs[i]) == NULL) + urb = p_priv->out_urbs[i]; + if (urb == NULL) continue; urb->dev = serial->dev; - /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ + /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe), 0); */ } /* get the terminal config for the setup message now so we don't * need to send 2 of them */ - cflag = port->tty->termios->c_cflag; device_port = port->number - port->serial->minor; - - /* Baud rate calculation takes baud rate as an integer - so other rates can be generated if desired. */ - baud_rate = tty_get_baud_rate(port->tty); - /* If no match or invalid, leave as default */ - if (baud_rate >= 0 - && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, - NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { - p_priv->baud = baud_rate; + if (tty) { + cflag = tty->termios->c_cflag; + /* Baud rate calculation takes baud rate as an integer + so other rates can be generated if desired. */ + baud_rate = tty_get_baud_rate(tty); + /* If no match or invalid, leave as default */ + if (baud_rate >= 0 + && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, + NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { + p_priv->baud = baud_rate; + } } - /* set CTS/RTS handshake etc. */ p_priv->cflag = cflag; p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; keyspan_send_setup(port, 1); - //mdelay(100); - //keyspan_set_termios(port, NULL); + /* mdelay(100); */ + /* keyspan_set_termios(port, NULL); */ return 0; } @@ -1301,7 +1294,8 @@ static inline void stop_urb(struct urb *urb) usb_kill_urb(urb); } -static void keyspan_close(struct usb_serial_port *port, struct file *filp) +static void keyspan_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int i; struct usb_serial *serial = port->serial; @@ -1311,15 +1305,15 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp) dbg("%s", __func__); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); - + p_priv->rts_state = 0; p_priv->dtr_state = 0; - + if (serial->dev) { keyspan_send_setup(port, 2); /* pilot-xfer seems to work best with this delay */ mdelay(100); - // keyspan_set_termios(port, NULL); + /* keyspan_set_termios(port, NULL); */ } /*while (p_priv->outcont_urb->status == -EINPROGRESS) { @@ -1338,11 +1332,11 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp) stop_urb(p_priv->out_urbs[i]); } } - port->tty = NULL; + port->port.tty = NULL; } - /* download the firmware to a pre-renumeration device */ -static int keyspan_fake_startup (struct usb_serial *serial) +/* download the firmware to a pre-renumeration device */ +static int keyspan_fake_startup(struct usb_serial *serial) { int response; const struct ihex_binrec *record; @@ -1352,10 +1346,11 @@ static int keyspan_fake_startup (struct usb_serial *serial) dbg("Keyspan startup version %04x product %04x", le16_to_cpu(serial->dev->descriptor.bcdDevice), le16_to_cpu(serial->dev->descriptor.idProduct)); - - if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) { + + if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) + != 0x8000) { dbg("Firmware already loaded. Quitting."); - return(1); + return 1; } /* Select firmware image on the basis of idProduct */ @@ -1379,11 +1374,11 @@ static int keyspan_fake_startup (struct usb_serial *serial) case keyspan_usa19_pre_product_id: fw_name = "keyspan/usa19.fw"; break; - + case keyspan_usa19qi_pre_product_id: fw_name = "keyspan/usa19qi.fw"; break; - + case keyspan_mpr_pre_product_id: fw_name = "keyspan/mpr.fw"; break; @@ -1391,15 +1386,15 @@ static int keyspan_fake_startup (struct usb_serial *serial) case keyspan_usa19qw_pre_product_id: fw_name = "keyspan/usa19qw.fw"; break; - + case keyspan_usa18x_pre_product_id: fw_name = "keyspan/usa18x.fw"; break; - + case keyspan_usa19w_pre_product_id: fw_name = "keyspan/usa19w.fw"; break; - + case keyspan_usa49w_pre_product_id: fw_name = "keyspan/usa49w.fw"; break; @@ -1431,8 +1426,7 @@ static int keyspan_fake_startup (struct usb_serial *serial) (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { - dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan" - "firmware (%d %04X %p %d)\n", + dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n", response, be32_to_cpu(record->addr), record->data, be16_to_cpu(record->len)); break; @@ -1445,7 +1439,7 @@ static int keyspan_fake_startup (struct usb_serial *serial) response = ezusb_set_reset(serial, 0); /* we don't want this device to have a driver assigned to it. */ - return (1); + return 1; } /* Helper functions used by keyspan_setup_urbs */ @@ -1467,7 +1461,7 @@ static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *se return NULL; } -static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint, +static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, int dir, void *ctx, char *buf, int len, void (*callback)(struct urb *)) { @@ -1478,10 +1472,10 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint, if (endpoint == -1) return NULL; /* endpoint not needed */ - dbg ("%s - alloc for endpoint %d.", __func__, endpoint); + dbg("%s - alloc for endpoint %d.", __func__, endpoint); urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (urb == NULL) { - dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint); + dbg("%s - alloc for endpoint %d failed.", __func__, endpoint); return NULL; } @@ -1554,7 +1548,7 @@ static struct callbacks { }, { /* msg_usa90 callbacks */ .instat_callback = usa90_instat_callback, - .glocont_callback = usa28_glocont_callback, + .glocont_callback = usa28_glocont_callback, .indat_callback = usa90_indat_callback, .outdat_callback = usa2x_outdat_callback, .inack_callback = usa28_inack_callback, @@ -1582,16 +1576,16 @@ static void keyspan_setup_urbs(struct usb_serial *serial) struct callbacks *cback; int endp; - dbg ("%s", __func__); + dbg("%s", __func__); s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; - /* Setup values for the various callback routines */ + /* Setup values for the various callback routines */ cback = &keyspan_callbacks[d_details->msg_format]; - /* Allocate and set up urbs for each one that is in use, - starting with instat endpoints */ + /* Allocate and set up urbs for each one that is in use, + starting with instat endpoints */ s_priv->instat_urb = keyspan_setup_urb (serial, d_details->instat_endpoint, USB_DIR_IN, serial, s_priv->instat_buf, INSTAT_BUFLEN, @@ -1607,8 +1601,8 @@ static void keyspan_setup_urbs(struct usb_serial *serial) serial, s_priv->glocont_buf, GLOCONT_BUFLEN, cback->glocont_callback); - /* Setup endpoints for each port specific thing */ - for (i = 0; i < d_details->num_ports; i ++) { + /* Setup endpoints for each port specific thing */ + for (i = 0; i < d_details->num_ports; i++) { port = serial->port[i]; p_priv = usb_get_serial_port_data(port); @@ -1644,8 +1638,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial) (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, port, p_priv->outcont_buffer, 64, cback->outcont_callback); - } - + } } /* usa19 function doesn't require prescaler */ @@ -1653,46 +1646,39 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum) { u32 b16, /* baud rate times 16 (actual rate used internally) */ - div, /* divisor */ + div, /* divisor */ cnt; /* inverse of divisor (programmed into 8051) */ - - dbg ("%s - %d.", __func__, baud_rate); - - /* prevent divide by zero... */ - if( (b16 = (baud_rate * 16L)) == 0) { - return (KEYSPAN_INVALID_BAUD_RATE); - } - /* Any "standard" rate over 57k6 is marginal on the USA-19 - as we run out of divisor resolution. */ - if (baud_rate > 57600) { - return (KEYSPAN_INVALID_BAUD_RATE); - } - - /* calculate the divisor and the counter (its inverse) */ - if( (div = (baudclk / b16)) == 0) { - return (KEYSPAN_INVALID_BAUD_RATE); - } - else { + dbg("%s - %d.", __func__, baud_rate); + + /* prevent divide by zero... */ + b16 = baud_rate * 16L; + if (b16 == 0) + return KEYSPAN_INVALID_BAUD_RATE; + /* Any "standard" rate over 57k6 is marginal on the USA-19 + as we run out of divisor resolution. */ + if (baud_rate > 57600) + return KEYSPAN_INVALID_BAUD_RATE; + + /* calculate the divisor and the counter (its inverse) */ + div = baudclk / b16; + if (div == 0) + return KEYSPAN_INVALID_BAUD_RATE; + else cnt = 0 - div; - } - if(div > 0xffff) { - return (KEYSPAN_INVALID_BAUD_RATE); - } + if (div > 0xffff) + return KEYSPAN_INVALID_BAUD_RATE; - /* return the counter values if non-null */ - if (rate_low) { + /* return the counter values if non-null */ + if (rate_low) *rate_low = (u8) (cnt & 0xff); - } - if (rate_hi) { + if (rate_hi) *rate_hi = (u8) ((cnt >> 8) & 0xff); - } - if (rate_low && rate_hi) { - dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low); - } - - return (KEYSPAN_BAUD_RATE_OK); + if (rate_low && rate_hi) + dbg("%s - %d %02x %02x.", + __func__, baud_rate, *rate_hi, *rate_low); + return KEYSPAN_BAUD_RATE_OK; } /* usa19hs function doesn't require prescaler */ @@ -1700,34 +1686,35 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum) { u32 b16, /* baud rate times 16 (actual rate used internally) */ - div; /* divisor */ - - dbg ("%s - %d.", __func__, baud_rate); + div; /* divisor */ - /* prevent divide by zero... */ - if( (b16 = (baud_rate * 16L)) == 0) - return (KEYSPAN_INVALID_BAUD_RATE); - + dbg("%s - %d.", __func__, baud_rate); + /* prevent divide by zero... */ + b16 = baud_rate * 16L; + if (b16 == 0) + return KEYSPAN_INVALID_BAUD_RATE; - /* calculate the divisor */ - if( (div = (baudclk / b16)) == 0) - return (KEYSPAN_INVALID_BAUD_RATE); + /* calculate the divisor */ + div = baudclk / b16; + if (div == 0) + return KEYSPAN_INVALID_BAUD_RATE; - if(div > 0xffff) - return (KEYSPAN_INVALID_BAUD_RATE); + if (div > 0xffff) + return KEYSPAN_INVALID_BAUD_RATE; - /* return the counter values if non-null */ - if (rate_low) + /* return the counter values if non-null */ + if (rate_low) *rate_low = (u8) (div & 0xff); - - if (rate_hi) + + if (rate_hi) *rate_hi = (u8) ((div >> 8) & 0xff); - - if (rate_low && rate_hi) - dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low); - - return (KEYSPAN_BAUD_RATE_OK); + + if (rate_low && rate_hi) + dbg("%s - %d %02x %02x.", + __func__, baud_rate, *rate_hi, *rate_low); + + return KEYSPAN_BAUD_RATE_OK; } static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, @@ -1735,64 +1722,61 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, { u32 b16, /* baud rate times 16 (actual rate used internally) */ clk, /* clock with 13/8 prescaler */ - div, /* divisor using 13/8 prescaler */ + div, /* divisor using 13/8 prescaler */ res, /* resulting baud rate using 13/8 prescaler */ diff, /* error using 13/8 prescaler */ smallest_diff; u8 best_prescaler; int i; - dbg ("%s - %d.", __func__, baud_rate); + dbg("%s - %d.", __func__, baud_rate); - /* prevent divide by zero */ - if( (b16 = baud_rate * 16L) == 0) { - return (KEYSPAN_INVALID_BAUD_RATE); - } + /* prevent divide by zero */ + b16 = baud_rate * 16L; + if (b16 == 0) + return KEYSPAN_INVALID_BAUD_RATE; - /* Calculate prescaler by trying them all and looking - for best fit */ - - /* start with largest possible difference */ + /* Calculate prescaler by trying them all and looking + for best fit */ + + /* start with largest possible difference */ smallest_diff = 0xffffffff; /* 0 is an invalid prescaler, used as a flag */ best_prescaler = 0; - for(i = 8; i <= 0xff; ++i) { + for (i = 8; i <= 0xff; ++i) { clk = (baudclk * 8) / (u32) i; - - if( (div = clk / b16) == 0) { + + div = clk / b16; + if (div == 0) continue; - } res = clk / div; - diff= (res > b16) ? (res-b16) : (b16-res); + diff = (res > b16) ? (res-b16) : (b16-res); - if(diff < smallest_diff) { + if (diff < smallest_diff) { best_prescaler = i; smallest_diff = diff; } } - if(best_prescaler == 0) { - return (KEYSPAN_INVALID_BAUD_RATE); - } + if (best_prescaler == 0) + return KEYSPAN_INVALID_BAUD_RATE; clk = (baudclk * 8) / (u32) best_prescaler; div = clk / b16; - /* return the divisor and prescaler if non-null */ - if (rate_low) { + /* return the divisor and prescaler if non-null */ + if (rate_low) *rate_low = (u8) (div & 0xff); - } - if (rate_hi) { + if (rate_hi) *rate_hi = (u8) ((div >> 8) & 0xff); - } if (prescaler) { *prescaler = best_prescaler; /* dbg("%s - %d %d", __func__, *prescaler, div); */ } - return (KEYSPAN_BAUD_RATE_OK); + return KEYSPAN_BAUD_RATE_OK; } /* USA-28 supports different maximum baud rates on each port */ @@ -1800,57 +1784,51 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum) { u32 b16, /* baud rate times 16 (actual rate used internally) */ - div, /* divisor */ + div, /* divisor */ cnt; /* inverse of divisor (programmed into 8051) */ - dbg ("%s - %d.", __func__, baud_rate); + dbg("%s - %d.", __func__, baud_rate); /* prevent divide by zero */ - if ((b16 = baud_rate * 16L) == 0) - return (KEYSPAN_INVALID_BAUD_RATE); - - /* calculate the divisor and the counter (its inverse) */ - if ((div = (KEYSPAN_USA28_BAUDCLK / b16)) == 0) { - return (KEYSPAN_INVALID_BAUD_RATE); - } - else { + b16 = baud_rate * 16L; + if (b16 == 0) + return KEYSPAN_INVALID_BAUD_RATE; + + /* calculate the divisor and the counter (its inverse) */ + div = KEYSPAN_USA28_BAUDCLK / b16; + if (div == 0) + return KEYSPAN_INVALID_BAUD_RATE; + else cnt = 0 - div; - } - /* check for out of range, based on portnum, - and return result */ - if(portnum == 0) { - if(div > 0xffff) - return (KEYSPAN_INVALID_BAUD_RATE); - } - else { - if(portnum == 1) { - if(div > 0xff) { - return (KEYSPAN_INVALID_BAUD_RATE); - } - } - else { - return (KEYSPAN_INVALID_BAUD_RATE); - } + /* check for out of range, based on portnum, + and return result */ + if (portnum == 0) { + if (div > 0xffff) + return KEYSPAN_INVALID_BAUD_RATE; + } else { + if (portnum == 1) { + if (div > 0xff) + return KEYSPAN_INVALID_BAUD_RATE; + } else + return KEYSPAN_INVALID_BAUD_RATE; } /* return the counter values if not NULL (port 1 will ignore retHi) */ - if (rate_low) { + if (rate_low) *rate_low = (u8) (cnt & 0xff); - } - if (rate_hi) { + if (rate_hi) *rate_hi = (u8) ((cnt >> 8) & 0xff); - } - dbg ("%s - %d OK.", __func__, baud_rate); - return (KEYSPAN_BAUD_RATE_OK); + dbg("%s - %d OK.", __func__, baud_rate); + return KEYSPAN_BAUD_RATE_OK; } static int keyspan_usa26_send_setup(struct usb_serial *serial, struct usb_serial_port *port, int reset_port) { - struct keyspan_usa26_portControlMessage msg; + struct keyspan_usa26_portControlMessage msg; struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; @@ -1858,7 +1836,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, struct urb *this_urb; int device_port, err; - dbg ("%s reset=%d", __func__, reset_port); + dbg("%s reset=%d", __func__, reset_port); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); @@ -1881,22 +1859,22 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - /* dbg ("%s - already writing", __func__); */ + /* dbg("%s - already writing", __func__); */ mdelay(5); - return(-1); + return -1; } - memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage)); - - /* Only set baud rate if it's changed */ + memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage)); + + /* Only set baud rate if it's changed */ if (p_priv->old_baud != p_priv->baud) { p_priv->old_baud = p_priv->baud; msg.setClocking = 0xff; if (d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { - dbg("%s - Invalid baud rate %d requested, using 9600.", __func__, - p_priv->baud); + &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dbg("%s - Invalid baud rate %d requested, using 9600.", + __func__, p_priv->baud); msg.baudLo = 0; msg.baudHi = 125; /* Values for 9600 baud */ msg.prescaler = 10; @@ -1922,7 +1900,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, if (p_priv->cflag & PARENB) { /* note USA_PARITY_NONE == 0 */ msg.lcr |= (p_priv->cflag & PARODD)? - USA_PARITY_ODD: USA_PARITY_EVEN; + USA_PARITY_ODD : USA_PARITY_EVEN; } msg.setLcr = 0xff; @@ -1963,7 +1941,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, /* Sending intermediate configs */ else { - msg._txOn = (! p_priv->break_on); + msg._txOn = (!p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txBreak = (p_priv->break_on); @@ -1975,23 +1953,23 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, msg.resetDataToggle = 0x0; } - /* Do handshaking outputs */ + /* Do handshaking outputs */ msg.setTxTriState_setRts = 0xff; msg.txTriState_rts = p_priv->rts_state; msg.setHskoa_setDtr = 0xff; msg.hskoa_dtr = p_priv->dtr_state; - + p_priv->resend_cont = 0; - memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); - + memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); + /* send the data out the device on control endpoint */ this_urb->transfer_buffer_length = sizeof(msg); this_urb->dev = serial->dev; - if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(this_urb, GFP_ATOMIC); + if (err != 0) dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err); - } #if 0 else { dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__ @@ -2007,14 +1985,14 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, struct usb_serial_port *port, int reset_port) { - struct keyspan_usa28_portControlMessage msg; + struct keyspan_usa28_portControlMessage msg; struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; struct urb *this_urb; int device_port, err; - dbg ("%s", __func__); + dbg("%s", __func__); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); @@ -2022,7 +2000,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, device_port = port->number - port->serial->minor; /* only do something if we have a bulk out endpoint */ - if ((this_urb = p_priv->outcont_urb) == NULL) { + this_urb = p_priv->outcont_urb; + if (this_urb == NULL) { dbg("%s - oops no urb.", __func__); return -1; } @@ -2032,17 +2011,18 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - dbg ("%s already writing", __func__); + dbg("%s already writing", __func__); mdelay(5); - return(-1); + return -1; } - memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage)); + memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage)); msg.setBaudRate = 1; if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk, - &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { - dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud); + &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dbg("%s - Invalid baud rate requested %d.", + __func__, p_priv->baud); msg.baudLo = 0xff; msg.baudHi = 0xb2; /* Values for 9600 baud */ } @@ -2053,7 +2033,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, msg.ctsFlowControl = (p_priv->flow_control == flow_cts); msg.xonFlowControl = 0; - /* Do handshaking outputs, DTR is inverted relative to RTS */ + /* Do handshaking outputs, DTR is inverted relative to RTS */ msg.rts = p_priv->rts_state; msg.dtr = p_priv->dtr_state; @@ -2095,7 +2075,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, } /* Sending intermediate configs */ else { - msg._txOn = (! p_priv->break_on); + msg._txOn = (!p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txForceXoff = 0; @@ -2109,15 +2089,15 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, } p_priv->resend_cont = 0; - memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); + memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); /* send the data out the device on control endpoint */ this_urb->transfer_buffer_length = sizeof(msg); this_urb->dev = serial->dev; - if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(this_urb, GFP_ATOMIC); + if (err != 0) dbg("%s - usb_submit_urb(setup) failed", __func__); - } #if 0 else { dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__, @@ -2140,7 +2120,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, struct urb *this_urb; int err, device_port; - dbg ("%s", __func__); + dbg("%s", __func__); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); @@ -2151,7 +2131,9 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, /* Work out which port within the device is being setup */ device_port = port->number - port->serial->minor; - dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port); + dbg("%s - endpoint %d port %d (%d)", + __func__, usb_pipeendpoint(this_urb->pipe), + port->number, device_port); /* Make sure we have an urb then send the message */ if (this_urb == NULL) { @@ -2165,30 +2147,30 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - /* dbg ("%s - already writing", __func__); */ + /* dbg("%s - already writing", __func__); */ mdelay(5); - return(-1); + return -1; } - memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage)); + memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage)); /*msg.portNumber = port->number;*/ msg.portNumber = device_port; - - /* Only set baud rate if it's changed */ + + /* Only set baud rate if it's changed */ if (p_priv->old_baud != p_priv->baud) { p_priv->old_baud = p_priv->baud; msg.setClocking = 0xff; if (d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { - dbg("%s - Invalid baud rate %d requested, using 9600.", __func__, - p_priv->baud); + &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dbg("%s - Invalid baud rate %d requested, using 9600.", + __func__, p_priv->baud); msg.baudLo = 0; msg.baudHi = 125; /* Values for 9600 baud */ msg.prescaler = 10; } - //msg.setPrescaler = 0xff; + /* msg.setPrescaler = 0xff; */ } msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1; @@ -2209,19 +2191,19 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, if (p_priv->cflag & PARENB) { /* note USA_PARITY_NONE == 0 */ msg.lcr |= (p_priv->cflag & PARODD)? - USA_PARITY_ODD: USA_PARITY_EVEN; + USA_PARITY_ODD : USA_PARITY_EVEN; } msg.setLcr = 0xff; msg.ctsFlowControl = (p_priv->flow_control == flow_cts); msg.xonFlowControl = 0; msg.setFlowControl = 0xff; - + msg.forwardingLength = 16; msg.xonChar = 17; msg.xoffChar = 19; - /* Opening port */ + /* Opening port */ if (reset_port == 1) { msg._txOn = 1; msg._txOff = 0; @@ -2253,7 +2235,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, } /* Sending intermediate configs */ else { - msg._txOn = (! p_priv->break_on); + msg._txOn = (!p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txBreak = (p_priv->break_on); @@ -2267,16 +2249,17 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, msg.disablePort = 0; } - /* Do handshaking outputs */ + /* Do handshaking outputs */ msg.setRts = 0xff; msg.rts = p_priv->rts_state; msg.setDtr = 0xff; msg.dtr = p_priv->dtr_state; - + p_priv->resend_cont = 0; - /* if the device is a 49wg, we send control message on usb control EP 0 */ + /* if the device is a 49wg, we send control message on usb + control EP 0 */ if (d_details->product_id == keyspan_usa49wg_product_id) { dr = (void *)(s_priv->ctrl_buf); @@ -2286,23 +2269,24 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, dr->wIndex = 0; dr->wLength = cpu_to_le16(sizeof(msg)); - memcpy (s_priv->glocont_buf, &msg, sizeof(msg)); + memcpy(s_priv->glocont_buf, &msg, sizeof(msg)); - usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0), - (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg), - usa49_glocont_callback, serial); + usb_fill_control_urb(this_urb, serial->dev, + usb_sndctrlpipe(serial->dev, 0), + (unsigned char *)dr, s_priv->glocont_buf, + sizeof(msg), usa49_glocont_callback, serial); } else { memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); - + /* send the data out the device on control endpoint */ this_urb->transfer_buffer_length = sizeof(msg); this_urb->dev = serial->dev; } - if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(this_urb, GFP_ATOMIC); + if (err != 0) dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err); - } #if 0 else { dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__, @@ -2318,7 +2302,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, struct usb_serial_port *port, int reset_port) { - struct keyspan_usa90_portControlMessage msg; + struct keyspan_usa90_portControlMessage msg; struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; @@ -2326,14 +2310,15 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, int err; u8 prescaler; - dbg ("%s", __func__); + dbg("%s", __func__); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); d_details = s_priv->device_details; /* only do something if we have a bulk out endpoint */ - if ((this_urb = p_priv->outcont_urb) == NULL) { + this_urb = p_priv->outcont_urb; + if (this_urb == NULL) { dbg("%s - oops no urb.", __func__); return -1; } @@ -2343,24 +2328,24 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - dbg ("%s already writing", __func__); + dbg("%s already writing", __func__); mdelay(5); - return(-1); + return -1; } - memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage)); + memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage)); - /* Only set baud rate if it's changed */ + /* Only set baud rate if it's changed */ if (p_priv->old_baud != p_priv->baud) { p_priv->old_baud = p_priv->baud; msg.setClocking = 0x01; if (d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) { - dbg("%s - Invalid baud rate %d requested, using 9600.", __func__, - p_priv->baud); + &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) { + dbg("%s - Invalid baud rate %d requested, using 9600.", + __func__, p_priv->baud); p_priv->baud = 9600; - d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, + d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk, &msg.baudHi, &msg.baudLo, &prescaler, 0); } msg.setRxMode = 1; @@ -2368,13 +2353,10 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, } /* modes must always be correctly specified */ - if (p_priv->baud > 57600) - { + if (p_priv->baud > 57600) { msg.rxMode = RXMODE_DMA; msg.txMode = TXMODE_DMA; - } - else - { + } else { msg.rxMode = RXMODE_BYHAND; msg.txMode = TXMODE_BYHAND; } @@ -2397,7 +2379,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, if (p_priv->cflag & PARENB) { /* note USA_PARITY_NONE == 0 */ msg.lcr |= (p_priv->cflag & PARODD)? - USA_PARITY_ODD: USA_PARITY_EVEN; + USA_PARITY_ODD : USA_PARITY_EVEN; } if (p_priv->old_cflag != p_priv->cflag) { p_priv->old_cflag = p_priv->cflag; @@ -2408,47 +2390,46 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, msg.txFlowControl = TXFLOW_CTS; msg.setTxFlowControl = 0x01; msg.setRxFlowControl = 0x01; - + msg.rxForwardingLength = 16; - msg.rxForwardingTimeout = 16; + msg.rxForwardingTimeout = 16; msg.txAckSetting = 0; msg.xonChar = 17; msg.xoffChar = 19; - /* Opening port */ + /* Opening port */ if (reset_port == 1) { msg.portEnabled = 1; msg.rxFlush = 1; msg.txBreak = (p_priv->break_on); } /* Closing port */ - else if (reset_port == 2) { + else if (reset_port == 2) msg.portEnabled = 0; - } /* Sending intermediate configs */ else { - if (port->open_count) + if (port->port.count) msg.portEnabled = 1; msg.txBreak = (p_priv->break_on); } - /* Do handshaking outputs */ + /* Do handshaking outputs */ msg.setRts = 0x01; msg.rts = p_priv->rts_state; msg.setDtr = 0x01; msg.dtr = p_priv->dtr_state; - + p_priv->resend_cont = 0; - memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); - + memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); + /* send the data out the device on control endpoint */ this_urb->transfer_buffer_length = sizeof(msg); this_urb->dev = serial->dev; - if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { + err = usb_submit_urb(this_urb, GFP_ATOMIC); + if (err != 0) dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err); - } return 0; } @@ -2463,7 +2444,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, struct urb *this_urb; int err, device_port; - dbg ("%s", __func__); + dbg("%s", __func__); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); @@ -2486,9 +2467,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - /* dbg ("%s - already writing", __func__); */ + /* dbg("%s - already writing", __func__); */ mdelay(5); - return(-1); + return -1; } memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage)); @@ -2501,9 +2482,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, msg.setClocking = 0xff; if (d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { - dbg("%s - Invalid baud rate %d requested, using 9600.", __func__, - p_priv->baud); + &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dbg("%s - Invalid baud rate %d requested, using 9600.", + __func__, p_priv->baud); msg.baudLo = 0; msg.baudHi = 125; /* Values for 9600 baud */ msg.prescaler = 10; @@ -2529,7 +2510,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, if (p_priv->cflag & PARENB) { /* note USA_PARITY_NONE == 0 */ msg.lcr |= (p_priv->cflag & PARODD)? - USA_PARITY_ODD: USA_PARITY_EVEN; + USA_PARITY_ODD : USA_PARITY_EVEN; } msg.setLcr = 0xff; @@ -2566,7 +2547,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, msg.resetDataToggle = 0; } else { /* Sending intermediate configs */ - msg._txOn = (! p_priv->break_on); + msg._txOn = (!p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txBreak = (p_priv->break_on); @@ -2606,7 +2587,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) struct keyspan_serial_private *s_priv; const struct keyspan_device_details *d_details; - dbg ("%s", __func__); + dbg("%s", __func__); s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; @@ -2633,7 +2614,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) /* Gets called by the "real" driver (ie once firmware is loaded and renumeration has taken place. */ -static int keyspan_startup (struct usb_serial *serial) +static int keyspan_startup(struct usb_serial *serial) { int i, err; struct usb_serial_port *port; @@ -2644,17 +2625,20 @@ static int keyspan_startup (struct usb_serial *serial) dbg("%s", __func__); for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) - if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct)) + if (d_details->product_id == + le16_to_cpu(serial->dev->descriptor.idProduct)) break; if (d_details == NULL) { - dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct)); + dev_err(&serial->dev->dev, "%s - unknown product id %x\n", + __func__, le16_to_cpu(serial->dev->descriptor.idProduct)); return 1; } /* Setup private data for serial driver */ s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); if (!s_priv) { - dbg("%s - kmalloc for keyspan_serial_private failed.", __func__); + dbg("%s - kmalloc for keyspan_serial_private failed.", + __func__); return -ENOMEM; } @@ -2664,10 +2648,11 @@ static int keyspan_startup (struct usb_serial *serial) /* Now setup per port private data */ for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); + p_priv = kzalloc(sizeof(struct keyspan_port_private), + GFP_KERNEL); if (!p_priv) { dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i); - return (1); + return 1; } p_priv->device_details = d_details; usb_set_serial_port_data(port, p_priv); @@ -2689,11 +2674,11 @@ static int keyspan_startup (struct usb_serial *serial) dbg("%s - submit indat urb failed %d", __func__, err); } - + return 0; } -static void keyspan_shutdown (struct usb_serial *serial) +static void keyspan_shutdown(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; @@ -2745,8 +2730,8 @@ static void keyspan_shutdown (struct usb_serial *serial) } } -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("keyspan/usa28.fw"); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index b52fb657a244..38b4582e0734 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -35,17 +35,18 @@ /* Function prototypes for Keyspan serial converter */ -static int keyspan_open (struct usb_serial_port *port, +static int keyspan_open (struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); -static void keyspan_close (struct usb_serial_port *port, +static void keyspan_close (struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); static int keyspan_startup (struct usb_serial *serial); static void keyspan_shutdown (struct usb_serial *serial); -static void keyspan_rx_throttle (struct usb_serial_port *port); -static void keyspan_rx_unthrottle (struct usb_serial_port *port); -static int keyspan_write_room (struct usb_serial_port *port); +static int keyspan_write_room (struct tty_struct *tty); -static int keyspan_write (struct usb_serial_port *port, +static int keyspan_write (struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count); @@ -53,18 +54,14 @@ static void keyspan_send_setup (struct usb_serial_port *port, int reset_port); -static int keyspan_chars_in_buffer (struct usb_serial_port *port); -static int keyspan_ioctl (struct usb_serial_port *port, - struct file *file, - unsigned int cmd, - unsigned long arg); -static void keyspan_set_termios (struct usb_serial_port *port, +static void keyspan_set_termios (struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); -static void keyspan_break_ctl (struct usb_serial_port *port, +static void keyspan_break_ctl (struct tty_struct *tty, int break_state); -static int keyspan_tiocmget (struct usb_serial_port *port, +static int keyspan_tiocmget (struct tty_struct *tty, struct file *file); -static int keyspan_tiocmset (struct usb_serial_port *port, +static int keyspan_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int keyspan_fake_startup (struct usb_serial *serial); @@ -138,7 +135,8 @@ static int keyspan_usa67_send_setup (struct usb_serial *serial, /* Product IDs post-renumeration. Note that the 28x and 28xb have the same id's post-renumeration but behave identically - so it's not an issue. */ + so it's not an issue. As such, the 28xb is not listed in any + of the device tables. */ #define keyspan_usa18x_product_id 0x0112 #define keyspan_usa19_product_id 0x0107 #define keyspan_usa19qi_product_id 0x010c @@ -482,7 +480,6 @@ static struct usb_device_id keyspan_ids_combined[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, - { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, @@ -532,7 +529,6 @@ static struct usb_device_id keyspan_2port_ids[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, - { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) }, { } /* Terminating entry */ }; @@ -568,10 +564,6 @@ static struct usb_serial_driver keyspan_1port_device = { .close = keyspan_close, .write = keyspan_write, .write_room = keyspan_write_room, - .chars_in_buffer = keyspan_chars_in_buffer, - .throttle = keyspan_rx_throttle, - .unthrottle = keyspan_rx_unthrottle, - .ioctl = keyspan_ioctl, .set_termios = keyspan_set_termios, .break_ctl = keyspan_break_ctl, .tiocmget = keyspan_tiocmget, @@ -592,10 +584,6 @@ static struct usb_serial_driver keyspan_2port_device = { .close = keyspan_close, .write = keyspan_write, .write_room = keyspan_write_room, - .chars_in_buffer = keyspan_chars_in_buffer, - .throttle = keyspan_rx_throttle, - .unthrottle = keyspan_rx_unthrottle, - .ioctl = keyspan_ioctl, .set_termios = keyspan_set_termios, .break_ctl = keyspan_break_ctl, .tiocmget = keyspan_tiocmget, @@ -616,10 +604,6 @@ static struct usb_serial_driver keyspan_4port_device = { .close = keyspan_close, .write = keyspan_write, .write_room = keyspan_write_room, - .chars_in_buffer = keyspan_chars_in_buffer, - .throttle = keyspan_rx_throttle, - .unthrottle = keyspan_rx_unthrottle, - .ioctl = keyspan_ioctl, .set_termios = keyspan_set_termios, .break_ctl = keyspan_break_ctl, .tiocmget = keyspan_tiocmget, diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 644a1eaaa376..040040a267d9 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -10,8 +10,9 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver - * + * See Documentation/usb/usb-serial.txt for more information on using this + * driver + * * (09/07/2001) gkh * cleaned up the Xircom support. Added ids for Entregra device which is * the same as the Xircom device. Enabled the code to be compiled for @@ -21,23 +22,24 @@ * support for Xircom PGSDB9 * * (05/31/2001) gkh - * switched from using spinlock to a semaphore, which fixes lots of problems. + * switched from using spinlock to a semaphore, which fixes lots of + * problems. * * (04/08/2001) gb * Identify version on module load. - * + * * (11/01/2000) Adam J. Richter * usb_device_id table support - * + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. - * + * * (08/28/2000) gkh * Added locks for SMP safeness. - * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more + * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more * than once. - * + * * (07/20/2000) borchers * - keyspan_pda_write no longer sleeps if it is called on interrupt time; * PPP and the line discipline with stty echo on can call write on @@ -55,14 +57,14 @@ * than done directly from the callback to avoid the race in write_chan * - keyspan_pda_chars_in_buffer also indicates its buffer is full if the * urb status is -EINPROGRESS, meaning it cannot write at the moment - * + * * (07/19/2000) gkh * Added module_init and module_exit functions to handle the fact that this * driver is a loadable module now. * * (03/26/2000) gkh * Split driver up into device specific pieces. - * + * */ @@ -78,7 +80,7 @@ #include <linux/workqueue.h> #include <linux/firmware.h> #include <linux/ihex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -135,7 +137,7 @@ static struct usb_device_id id_table_combined [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver keyspan_pda_driver = { .name = "keyspan_pda", @@ -159,9 +161,9 @@ static struct usb_device_id id_table_fake [] = { #ifdef XIRCOM static struct usb_device_id id_table_fake_xircom [] = { - { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) }, - { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) }, - { } + { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) }, + { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) }, + { } }; #endif @@ -171,7 +173,7 @@ static void keyspan_pda_wakeup_write(struct work_struct *work) container_of(work, struct keyspan_pda_private, wakeup_work); struct usb_serial_port *port = priv->port; - tty_wakeup(port->tty); + tty_wakeup(port->port.tty); } static void keyspan_pda_request_unthrottle(struct work_struct *work) @@ -184,7 +186,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) dbg(" request_unthrottle"); /* ask the device to tell us when the tx buffer becomes sufficiently empty */ - result = usb_control_msg(serial->dev, + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 7, /* request_unthrottle */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE @@ -195,17 +197,16 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) 0, 2000); if (result < 0) - dbg("%s - error %d from usb_control_msg", + dbg("%s - error %d from usb_control_msg", __func__, result); } -static void keyspan_pda_rx_interrupt (struct urb *urb) +static void keyspan_pda_rx_interrupt(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct tty_struct *tty = port->tty; + struct tty_struct *tty = port->port.tty; unsigned char *data = urb->transfer_buffer; - int i; int retval; int status = urb->status; struct keyspan_pda_private *priv; @@ -228,14 +229,13 @@ static void keyspan_pda_rx_interrupt (struct urb *urb) goto exit; } - /* see if the message is data or a status interrupt */ + /* see if the message is data or a status interrupt */ switch (data[0]) { case 0: /* rest of message is rx data */ if (urb->actual_length) { - for (i = 1; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } + tty_insert_flip_string(tty, data + 1, + urb->actual_length - 1); tty_flip_buffer_push(tty); } break; @@ -259,14 +259,14 @@ static void keyspan_pda_rx_interrupt (struct urb *urb) } exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err ("%s - usb_submit_urb failed with result %d", + err("%s - usb_submit_urb failed with result %d", __func__, retval); } -static void keyspan_pda_rx_throttle (struct usb_serial_port *port) +static void keyspan_pda_rx_throttle(struct tty_struct *tty) { /* stop receiving characters. We just turn off the URB request, and let chars pile up in the device. If we're doing hardware @@ -274,14 +274,15 @@ static void keyspan_pda_rx_throttle (struct usb_serial_port *port) fills up. If we're doing XON/XOFF, this would be a good time to send an XOFF, although it might make sense to foist that off upon the device too. */ - + struct usb_serial_port *port = tty->driver_data; dbg("keyspan_pda_rx_throttle port %d", port->number); usb_kill_urb(port->interrupt_in_urb); } -static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port) +static void keyspan_pda_rx_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; /* just restart the receive interrupt URB */ dbg("keyspan_pda_rx_unthrottle port %d", port->number); port->interrupt_in_urb->dev = port->serial->dev; @@ -291,32 +292,52 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port) } -static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud) +static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud) { int rc; int bindex; - switch(baud) { - case 110: bindex = 0; break; - case 300: bindex = 1; break; - case 1200: bindex = 2; break; - case 2400: bindex = 3; break; - case 4800: bindex = 4; break; - case 9600: bindex = 5; break; - case 19200: bindex = 6; break; - case 38400: bindex = 7; break; - case 57600: bindex = 8; break; - case 115200: bindex = 9; break; - default: - bindex = 5; /* Default to 9600 */ - baud = 9600; + switch (baud) { + case 110: + bindex = 0; + break; + case 300: + bindex = 1; + break; + case 1200: + bindex = 2; + break; + case 2400: + bindex = 3; + break; + case 4800: + bindex = 4; + break; + case 9600: + bindex = 5; + break; + case 19200: + bindex = 6; + break; + case 38400: + bindex = 7; + break; + case 57600: + bindex = 8; + break; + case 115200: + bindex = 9; + break; + default: + bindex = 5; /* Default to 9600 */ + baud = 9600; } /* rather than figure out how to sleep while waiting for this to complete, I just use the "legacy" API. */ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0, /* set baud */ - USB_TYPE_VENDOR + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, /* type */ bindex, /* value */ @@ -330,8 +351,9 @@ static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud) } -static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state) +static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; int value; int result; @@ -341,11 +363,11 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state else value = 0; /* clear break */ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - 4, /* set break */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - value, 0, NULL, 0, 2000); + 4, /* set break */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + value, 0, NULL, 0, 2000); if (result < 0) - dbg("%s - error %d from usb_control_msg", + dbg("%s - error %d from usb_control_msg", __func__, result); /* there is something funky about this.. the TCSBRK that 'cu' performs ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4 @@ -354,8 +376,8 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state } -static void keyspan_pda_set_termios (struct usb_serial_port *port, - struct ktermios *old_termios) +static void keyspan_pda_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; speed_t speed; @@ -380,7 +402,7 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port, For now, just do baud. */ - speed = tty_get_baud_rate(port->tty); + speed = tty_get_baud_rate(tty); speed = keyspan_pda_setbaud(serial, speed); if (speed == 0) { @@ -390,8 +412,8 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port, } /* Only speed can change so copy the old h/w parameters then encode the new speed */ - tty_termios_copy_hw(port->tty->termios, old_termios); - tty_encode_baud_rate(port->tty, speed, speed); + tty_termios_copy_hw(tty->termios, old_termios); + tty_encode_baud_rate(tty, speed, speed); } @@ -408,7 +430,7 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial, 3, /* get pins */ USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, 0, 0, &data, 1, 2000); - if (rc > 0) + if (rc >= 0) *value = data; return rc; } @@ -425,8 +447,9 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial, return rc; } -static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file) +static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; int rc; unsigned char status; @@ -445,9 +468,10 @@ static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file) return value; } -static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file, +static int keyspan_pda_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; int rc; unsigned char status; @@ -469,23 +493,8 @@ static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file, return rc; } -static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case TIOCMIWAIT: - /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ - /* TODO */ - case TIOCGICOUNT: - /* return count of modemline transitions */ - return 0; /* TODO */ - } - - return -ENOIOCTLCMD; -} - -static int keyspan_pda_write(struct usb_serial_port *port, - const unsigned char *buf, int count) +static int keyspan_pda_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; int request_unthrottle = 0; @@ -501,10 +510,10 @@ static int keyspan_pda_write(struct usb_serial_port *port, select() or poll() too) until we receive that unthrottle interrupt. Block if we can't write anything at all, otherwise write as much as we can. */ - dbg("keyspan_pda_write(%d)",count); + dbg("keyspan_pda_write(%d)", count); if (count == 0) { dbg(" write request of 0 bytes"); - return (0); + return 0; } /* we might block because of: @@ -531,7 +540,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, scheduler time, since usb_control_msg() sleeps. */ if (count > priv->tx_room && !in_interrupt()) { unsigned char room; - rc = usb_control_msg(serial->dev, + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 6, /* write_room */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE @@ -562,7 +571,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, if (count) { /* now transfer data */ - memcpy (port->write_urb->transfer_buffer, buf, count); + memcpy(port->write_urb->transfer_buffer, buf, count); /* send the data out the bulk port */ port->write_urb->transfer_buffer_length = count; @@ -574,8 +583,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, dbg(" usb_submit_urb(write bulk) failed"); goto exit; } - } - else { + } else { /* There wasn't any room left, so we are throttled until the buffer empties a bit */ request_unthrottle = 1; @@ -594,7 +602,7 @@ exit: } -static void keyspan_pda_write_bulk_callback (struct urb *urb) +static void keyspan_pda_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct keyspan_pda_private *priv; @@ -607,22 +615,21 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb) } -static int keyspan_pda_write_room (struct usb_serial_port *port) +static int keyspan_pda_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct keyspan_pda_private *priv; - priv = usb_get_serial_port_data(port); - /* used by n_tty.c for processing of tabs and such. Giving it our conservative guess is probably good enough, but needs testing by running a console through the device. */ - - return (priv->tx_room); + return priv->tx_room; } -static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) +static int keyspan_pda_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct keyspan_pda_private *priv; unsigned long flags; int ret = 0; @@ -640,7 +647,8 @@ static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) } -static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp) +static int keyspan_pda_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; unsigned char room; @@ -672,8 +680,8 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp) /* the normal serial device seems to always turn on DTR and RTS here, so do the same */ - if (port->tty->termios->c_cflag & CBAUD) - keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) ); + if (tty && (tty->termios->c_cflag & CBAUD)) + keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2)); else keyspan_pda_set_modem_info(serial, 0); @@ -690,13 +698,15 @@ error: } -static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp) +static void keyspan_pda_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; if (serial->dev) { - /* the normal serial device seems to always shut off DTR and RTS now */ - if (port->tty->termios->c_cflag & HUPCL) + /* the normal serial device seems to always shut + off DTR and RTS now */ + if (tty->termios->c_cflag & HUPCL) keyspan_pda_set_modem_info(serial, 0); /* shutdown our bulk reads and writes */ @@ -707,7 +717,7 @@ static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp) /* download the firmware to a "fake" device (pre-renumeration) */ -static int keyspan_pda_fake_startup (struct usb_serial *serial) +static int keyspan_pda_fake_startup(struct usb_serial *serial) { int response; const char *fw_name; @@ -756,10 +766,10 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial) response = ezusb_set_reset(serial, 0); /* we want this device to fail to have a driver assigned to it. */ - return (1); + return 1; } -static int keyspan_pda_startup (struct usb_serial *serial) +static int keyspan_pda_startup(struct usb_serial *serial) { struct keyspan_pda_private *priv; @@ -769,20 +779,20 @@ static int keyspan_pda_startup (struct usb_serial *serial) priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL); if (!priv) - return (1); /* error */ + return 1; /* error */ usb_set_serial_port_data(serial->port[0], priv); init_waitqueue_head(&serial->port[0]->write_wait); INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); priv->serial = serial; priv->port = serial->port[0]; - return (0); + return 0; } -static void keyspan_pda_shutdown (struct usb_serial *serial) +static void keyspan_pda_shutdown(struct usb_serial *serial) { dbg("%s", __func__); - + kfree(usb_get_serial_port_data(serial->port[0])); } @@ -832,7 +842,6 @@ static struct usb_serial_driver keyspan_pda_device = { .chars_in_buffer = keyspan_pda_chars_in_buffer, .throttle = keyspan_pda_rx_throttle, .unthrottle = keyspan_pda_rx_unthrottle, - .ioctl = keyspan_pda_ioctl, .set_termios = keyspan_pda_set_termios, .break_ctl = keyspan_pda_break_ctl, .tiocmget = keyspan_pda_tiocmget, @@ -842,7 +851,7 @@ static struct usb_serial_driver keyspan_pda_device = { }; -static int __init keyspan_pda_init (void) +static int __init keyspan_pda_init(void) { int retval; retval = usb_serial_register(&keyspan_pda_device); @@ -863,7 +872,7 @@ static int __init keyspan_pda_init (void) goto failed_usb_register; info(DRIVER_DESC " " DRIVER_VERSION); return 0; -failed_usb_register: +failed_usb_register: #ifdef XIRCOM usb_serial_deregister(&xircom_pgs_fake_device); failed_xircom_register: @@ -880,15 +889,15 @@ failed_pda_register: } -static void __exit keyspan_pda_exit (void) +static void __exit keyspan_pda_exit(void) { - usb_deregister (&keyspan_pda_driver); - usb_serial_deregister (&keyspan_pda_device); + usb_deregister(&keyspan_pda_driver); + usb_serial_deregister(&keyspan_pda_device); #ifdef KEYSPAN - usb_serial_deregister (&keyspan_pda_fake_device); + usb_serial_deregister(&keyspan_pda_fake_device); #endif #ifdef XIRCOM - usb_serial_deregister (&xircom_pgs_fake_device); + usb_serial_deregister(&xircom_pgs_fake_device); #endif } @@ -896,8 +905,8 @@ static void __exit keyspan_pda_exit (void) module_init(keyspan_pda_init); module_exit(keyspan_pda_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index f328948d74e3..b84dddc71124 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -15,12 +15,12 @@ * Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided * information that was not already available. * - * It seems that KLSI bought some silicon-design information from ScanLogic, + * It seems that KLSI bought some silicon-design information from ScanLogic, * whose SL11R processor is at the core of the KL5KUSB chipset from KLSI. * KLSI has firmware available for their devices; it is probable that the * firmware differs from that used by KLSI in their products. If you have an - * original KLSI device and can provide some information on it, I would be - * most interested in adding support for it here. If you have any information + * original KLSI device and can provide some information on it, I would be + * most interested in adding support for it here. If you have any information * on the protocol used (or find errors in my reverse-engineered stuff), please * let me know. * @@ -40,7 +40,7 @@ * 0.2 - TIOCMGET works, so autopilot(1) can be used! * 0.1 - can be used to to pilot-xfer -p /dev/ttyUSB0 -l * - * The driver skeleton is mainly based on mct_u232.c and various other + * The driver skeleton is mainly based on mct_u232.c and various other * pieces of code shamelessly copied from the drivers/usb/serial/ directory. */ @@ -53,7 +53,7 @@ #include <linux/tty_driver.h> #include <linux/tty_flip.h> #include <linux/module.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unaligned.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -72,33 +72,25 @@ static int debug; /* * Function prototypes */ -static int klsi_105_startup (struct usb_serial *serial); -static void klsi_105_shutdown (struct usb_serial *serial); -static int klsi_105_open (struct usb_serial_port *port, - struct file *filp); -static void klsi_105_close (struct usb_serial_port *port, - struct file *filp); -static int klsi_105_write (struct usb_serial_port *port, - const unsigned char *buf, - int count); -static void klsi_105_write_bulk_callback (struct urb *urb); -static int klsi_105_chars_in_buffer (struct usb_serial_port *port); -static int klsi_105_write_room (struct usb_serial_port *port); - -static void klsi_105_read_bulk_callback (struct urb *urb); -static void klsi_105_set_termios (struct usb_serial_port *port, - struct ktermios *old); -static void klsi_105_throttle (struct usb_serial_port *port); -static void klsi_105_unthrottle (struct usb_serial_port *port); -/* -static void klsi_105_break_ctl (struct usb_serial_port *port, - int break_state ); - */ -static int klsi_105_tiocmget (struct usb_serial_port *port, - struct file *file); -static int klsi_105_tiocmset (struct usb_serial_port *port, - struct file *file, unsigned int set, - unsigned int clear); +static int klsi_105_startup(struct usb_serial *serial); +static void klsi_105_shutdown(struct usb_serial *serial); +static int klsi_105_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void klsi_105_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static int klsi_105_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count); +static void klsi_105_write_bulk_callback(struct urb *urb); +static int klsi_105_chars_in_buffer(struct tty_struct *tty); +static int klsi_105_write_room(struct tty_struct *tty); +static void klsi_105_read_bulk_callback(struct urb *urb); +static void klsi_105_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static void klsi_105_throttle(struct tty_struct *tty); +static void klsi_105_unthrottle(struct tty_struct *tty); +static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file); +static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); /* * All of the device info needed for the KLSI converters. @@ -109,7 +101,7 @@ static struct usb_device_id id_table [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver kl5kusb105d_driver = { .name = "kl5kusb105d", @@ -134,7 +126,7 @@ static struct usb_serial_driver kl5kusb105d_device = { .write_bulk_callback = klsi_105_write_bulk_callback, .chars_in_buffer = klsi_105_chars_in_buffer, .write_room = klsi_105_write_room, - .read_bulk_callback =klsi_105_read_bulk_callback, + .read_bulk_callback = klsi_105_read_bulk_callback, .set_termios = klsi_105_set_termios, /*.break_ctl = klsi_105_break_ctl,*/ .tiocmget = klsi_105_tiocmget, @@ -161,7 +153,7 @@ struct klsi_105_private { struct ktermios termios; unsigned long line_state; /* modem line settings */ /* write pool */ - struct urb * write_urb_pool[NUM_URBS]; + struct urb *write_urb_pool[NUM_URBS]; spinlock_t lock; unsigned long bytes_in; unsigned long bytes_out; @@ -180,15 +172,15 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port, { int rc; - rc = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - KL5KUSB105A_SIO_SET_DATA, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE, - 0, /* value */ - 0, /* index */ - settings, - sizeof(struct klsi_105_port_settings), - KLSI_TIMEOUT); + rc = usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), + KL5KUSB105A_SIO_SET_DATA, + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE, + 0, /* value */ + 0, /* index */ + settings, + sizeof(struct klsi_105_port_settings), + KLSI_TIMEOUT); if (rc < 0) err("Change port settings failed (error = %d)", rc); info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d", @@ -196,7 +188,7 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port, settings->pktlen, settings->baudrate, settings->databits, settings->unknown1, settings->unknown2); - return rc; + return rc; } /* klsi_105_chg_port_settings */ /* translate a 16-bit status value from the device to linux's TIO bits */ @@ -210,9 +202,9 @@ static unsigned long klsi_105_status2linestate(const __u16 status) return res; } -/* +/* * Read line control via vendor command and return result through - * *line_state_p + * *line_state_p */ /* It seems that the status buffer has always only 2 bytes length */ #define KLSI_STATUSBUF_LEN 2 @@ -220,14 +212,14 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, unsigned long *line_state_p) { int rc; - __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1}; + __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1}; __u16 status; info("%s - sending SIO Poll request", __func__); - rc = usb_control_msg(port->serial->dev, + rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), KL5KUSB105A_SIO_POLL, - USB_TYPE_VENDOR | USB_DIR_IN, + USB_TYPE_VENDOR | USB_DIR_IN, 0, /* value */ 0, /* index */ status_buf, KLSI_STATUSBUF_LEN, @@ -236,15 +228,14 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, if (rc < 0) err("Reading line status failed (error = %d)", rc); else { - status = le16_to_cpu(get_unaligned((__le16 *)status_buf)); + status = get_unaligned_le16(status_buf); info("%s - read status %x %x", __func__, status_buf[0], status_buf[1]); *line_state_p = klsi_105_status2linestate(status); } - - return rc; + return rc; } @@ -252,7 +243,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, * Driver's tty interface functions */ -static int klsi_105_startup (struct usb_serial *serial) +static int klsi_105_startup(struct usb_serial *serial) { struct klsi_105_private *priv; int i, j; @@ -262,7 +253,7 @@ static int klsi_105_startup (struct usb_serial *serial) */ /* allocate the private data structure */ - for (i=0; i<serial->num_ports; i++) { + for (i = 0; i < serial->num_ports; i++) { priv = kmalloc(sizeof(struct klsi_105_private), GFP_KERNEL); if (!priv) { @@ -283,9 +274,9 @@ static int klsi_105_startup (struct usb_serial *serial) priv->bytes_out = 0; usb_set_serial_port_data(serial->port[i], priv); - spin_lock_init (&priv->lock); - for (j=0; j<NUM_URBS; j++) { - struct urb* urb = usb_alloc_urb(0, GFP_KERNEL); + spin_lock_init(&priv->lock); + for (j = 0; j < NUM_URBS; j++) { + struct urb *urb = usb_alloc_urb(0, GFP_KERNEL); priv->write_urb_pool[j] = urb; if (urb == NULL) { @@ -293,10 +284,11 @@ static int klsi_105_startup (struct usb_serial *serial) goto err_cleanup; } - urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, - GFP_KERNEL); + urb->transfer_buffer = + kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (!urb->transfer_buffer) { - err("%s - out of memory for urb buffers.", __func__); + err("%s - out of memory for urb buffers.", + __func__); goto err_cleanup; } } @@ -304,13 +296,13 @@ static int klsi_105_startup (struct usb_serial *serial) /* priv->termios is left uninitalized until port opening */ init_waitqueue_head(&serial->port[i]->write_wait); } - + return 0; err_cleanup: for (; i >= 0; i--) { priv = usb_get_serial_port_data(serial->port[i]); - for (j=0; j < NUM_URBS; j++) { + for (j = 0; j < NUM_URBS; j++) { if (priv->write_urb_pool[j]) { kfree(priv->write_urb_pool[j]->transfer_buffer); usb_free_urb(priv->write_urb_pool[j]); @@ -322,22 +314,23 @@ err_cleanup: } /* klsi_105_startup */ -static void klsi_105_shutdown (struct usb_serial *serial) +static void klsi_105_shutdown(struct usb_serial *serial) { int i; - + dbg("%s", __func__); /* stop reads and writes on all ports */ - for (i=0; i < serial->num_ports; ++i) { - struct klsi_105_private *priv = usb_get_serial_port_data(serial->port[i]); + for (i = 0; i < serial->num_ports; ++i) { + struct klsi_105_private *priv = + usb_get_serial_port_data(serial->port[i]); unsigned long flags; if (priv) { /* kill our write urb pool */ int j; struct urb **write_urbs = priv->write_urb_pool; - spin_lock_irqsave(&priv->lock,flags); + spin_lock_irqsave(&priv->lock, flags); for (j = 0; j < NUM_URBS; j++) { if (write_urbs[j]) { @@ -349,19 +342,18 @@ static void klsi_105_shutdown (struct usb_serial *serial) * oopses. */ /* usb_kill_urb(write_urbs[j]); */ kfree(write_urbs[j]->transfer_buffer); - usb_free_urb (write_urbs[j]); + usb_free_urb(write_urbs[j]); } } - - spin_unlock_irqrestore (&priv->lock, flags); - + spin_unlock_irqrestore(&priv->lock, flags); kfree(priv); usb_set_serial_port_data(serial->port[i], NULL); } } } /* klsi_105_shutdown */ -static int klsi_105_open (struct usb_serial_port *port, struct file *filp) +static int klsi_105_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct klsi_105_private *priv = usb_get_serial_port_data(port); int retval = 0; @@ -375,11 +367,11 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp) /* force low_latency on so that our tty_push actually forces * the data through - * port->tty->low_latency = 1; */ + * tty->low_latency = 1; */ /* Do a defined restart: * Set up sane default baud rate and send the 'READ_ON' - * vendor command. + * vendor command. * FIXME: set modem line control (how?) * Then read the modem line control and store values in * priv->line_state. @@ -390,24 +382,24 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp) cfg.unknown1 = 0; cfg.unknown2 = 1; klsi_105_chg_port_settings(port, &cfg); - + /* set up termios structure */ - spin_lock_irqsave (&priv->lock, flags); - priv->termios.c_iflag = port->tty->termios->c_iflag; - priv->termios.c_oflag = port->tty->termios->c_oflag; - priv->termios.c_cflag = port->tty->termios->c_cflag; - priv->termios.c_lflag = port->tty->termios->c_lflag; - for (i=0; i<NCCS; i++) - priv->termios.c_cc[i] = port->tty->termios->c_cc[i]; + spin_lock_irqsave(&priv->lock, flags); + priv->termios.c_iflag = tty->termios->c_iflag; + priv->termios.c_oflag = tty->termios->c_oflag; + priv->termios.c_cflag = tty->termios->c_cflag; + priv->termios.c_lflag = tty->termios->c_lflag; + for (i = 0; i < NCCS; i++) + priv->termios.c_cc[i] = tty->termios->c_cc[i]; priv->cfg.pktlen = cfg.pktlen; priv->cfg.baudrate = cfg.baudrate; priv->cfg.databits = cfg.databits; priv->cfg.unknown1 = cfg.unknown1; priv->cfg.unknown2 = cfg.unknown2; - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); /* READ_ON and urb submission */ - usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, @@ -423,7 +415,7 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp) } rc = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev,0), + usb_sndctrlpipe(port->serial->dev, 0), KL5KUSB105A_SIO_CONFIGURE, USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE, KL5KUSB105A_SIO_CONFIGURE_READ_ON, @@ -434,14 +426,14 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp) if (rc < 0) { err("Enabling read failed (error = %d)", rc); retval = rc; - } else + } else dbg("%s - enabled reading", __func__); rc = klsi_105_get_line_state(port, &line_state); if (rc >= 0) { - spin_lock_irqsave (&priv->lock, flags); + spin_lock_irqsave(&priv->lock, flags); priv->line_state = line_state; - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - read line state 0x%lx", __func__, line_state); retval = 0; } else @@ -452,7 +444,8 @@ exit: } /* klsi_105_open */ -static void klsi_105_close (struct usb_serial_port *port, struct file *filp) +static void klsi_105_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct klsi_105_private *priv = usb_get_serial_port_data(port); int rc; @@ -462,14 +455,14 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp) mutex_lock(&port->serial->disc_mutex); if (!port->serial->disconnected) { /* send READ_OFF */ - rc = usb_control_msg (port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - KL5KUSB105A_SIO_CONFIGURE, - USB_TYPE_VENDOR | USB_DIR_OUT, - KL5KUSB105A_SIO_CONFIGURE_READ_OFF, - 0, /* index */ - NULL, 0, - KLSI_TIMEOUT); + rc = usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), + KL5KUSB105A_SIO_CONFIGURE, + USB_TYPE_VENDOR | USB_DIR_OUT, + KL5KUSB105A_SIO_CONFIGURE_READ_OFF, + 0, /* index */ + NULL, 0, + KLSI_TIMEOUT); if (rc < 0) err("Disabling read failed (error = %d)", rc); } @@ -482,23 +475,24 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp) /* FIXME */ /* wgg - do I need this? I think so. */ usb_kill_urb(port->interrupt_in_urb); - info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out); + info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", + priv->bytes_in, priv->bytes_out); } /* klsi_105_close */ /* We need to write a complete 64-byte data block and encode the - * number actually sent in the first double-byte, LSB-order. That + * number actually sent in the first double-byte, LSB-order. That * leaves at most 62 bytes of payload. */ #define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */ -static int klsi_105_write (struct usb_serial_port *port, - const unsigned char *buf, int count) +static int klsi_105_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count) { struct klsi_105_private *priv = usb_get_serial_port_data(port); int result, size; - int bytes_sent=0; + int bytes_sent = 0; dbg("%s - port %d", __func__, port->number); @@ -507,34 +501,37 @@ static int klsi_105_write (struct usb_serial_port *port, struct urb *urb = NULL; unsigned long flags; int i; - /* since the pool is per-port we might not need the spin lock !? */ - spin_lock_irqsave (&priv->lock, flags); - for (i=0; i<NUM_URBS; i++) { + /* since the pool is per-port we might not need + the spin lock !? */ + spin_lock_irqsave(&priv->lock, flags); + for (i = 0; i < NUM_URBS; i++) { if (priv->write_urb_pool[i]->status != -EINPROGRESS) { urb = priv->write_urb_pool[i]; dbg("%s - using pool URB %d", __func__, i); break; } } - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); - if (urb==NULL) { + if (urb == NULL) { dbg("%s - no more free urbs", __func__); goto exit; } if (urb->transfer_buffer == NULL) { - urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); + urb->transfer_buffer = + kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); if (urb->transfer_buffer == NULL) { err("%s - no more kernel memory...", __func__); goto exit; } } - size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET); - size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET); + size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET); + size = min(size, URB_TRANSFER_BUFFER_SIZE - + KLSI_105_DATA_OFFSET); - memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); + memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); /* write payload size into transfer buffer */ ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF); @@ -552,7 +549,8 @@ static int klsi_105_write (struct usb_serial_port *port, /* send the data out the bulk port */ result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", __func__, result); + err("%s - failed submitting write urb, error %d", + __func__, result); goto exit; } buf += size; @@ -561,12 +559,12 @@ static int klsi_105_write (struct usb_serial_port *port, } exit: /* lockless, but it's for debug info only... */ - priv->bytes_out+=bytes_sent; + priv->bytes_out += bytes_sent; return bytes_sent; /* that's how much we wrote */ } /* klsi_105_write */ -static void klsi_105_write_bulk_callback ( struct urb *urb) +static void klsi_105_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; int status = urb->status; @@ -584,50 +582,50 @@ static void klsi_105_write_bulk_callback ( struct urb *urb) /* return number of characters currently in the writing process */ -static int klsi_105_chars_in_buffer (struct usb_serial_port *port) +static int klsi_105_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int chars = 0; int i; unsigned long flags; struct klsi_105_private *priv = usb_get_serial_port_data(port); - spin_lock_irqsave (&priv->lock, flags); + spin_lock_irqsave(&priv->lock, flags); for (i = 0; i < NUM_URBS; ++i) { - if (priv->write_urb_pool[i]->status == -EINPROGRESS) { + if (priv->write_urb_pool[i]->status == -EINPROGRESS) chars += URB_TRANSFER_BUFFER_SIZE; - } } - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - returns %d", __func__, chars); - return (chars); + return chars; } -static int klsi_105_write_room (struct usb_serial_port *port) +static int klsi_105_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; unsigned long flags; int i; int room = 0; struct klsi_105_private *priv = usb_get_serial_port_data(port); - spin_lock_irqsave (&priv->lock, flags); + spin_lock_irqsave(&priv->lock, flags); for (i = 0; i < NUM_URBS; ++i) { - if (priv->write_urb_pool[i]->status != -EINPROGRESS) { + if (priv->write_urb_pool[i]->status != -EINPROGRESS) room += URB_TRANSFER_BUFFER_SIZE; - } } - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - returns %d", __func__, room); - return (room); + return room; } -static void klsi_105_read_bulk_callback (struct urb *urb) +static void klsi_105_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct klsi_105_private *priv = usb_get_serial_port_data(port); @@ -660,13 +658,13 @@ static void klsi_105_read_bulk_callback (struct urb *urb) } else { int bytes_sent = ((__u8 *) data)[0] + ((unsigned int) ((__u8 *) data)[1] << 8); - tty = port->tty; + tty = port->port.tty; /* we should immediately resubmit the URB, before attempting * to pass the data on to the tty layer. But that needs locking * against re-entry an then mixed-up data because of * intermixed tty_flip_buffer_push()s * FIXME - */ + */ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); @@ -686,7 +684,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb) priv->bytes_in += bytes_sent; } /* Continue trying to always read */ - usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, @@ -695,15 +693,16 @@ static void klsi_105_read_bulk_callback (struct urb *urb) port); rc = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (rc) - err("%s - failed resubmitting read urb, error %d", __func__, rc); + err("%s - failed resubmitting read urb, error %d", + __func__, rc); } /* klsi_105_read_bulk_callback */ -static void klsi_105_set_termios (struct usb_serial_port *port, - struct ktermios *old_termios) +static void klsi_105_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, + struct ktermios *old_termios) { struct klsi_105_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty = port->tty; unsigned int iflag = tty->termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int cflag = tty->termios->c_cflag; @@ -711,65 +710,63 @@ static void klsi_105_set_termios (struct usb_serial_port *port, struct klsi_105_port_settings cfg; unsigned long flags; speed_t baud; - + /* lock while we are modifying the settings */ - spin_lock_irqsave (&priv->lock, flags); - + spin_lock_irqsave(&priv->lock, flags); + /* * Update baud rate */ baud = tty_get_baud_rate(tty); - if( (cflag & CBAUD) != (old_cflag & CBAUD) ) { - /* reassert DTR and (maybe) RTS on transition from B0 */ - if( (old_cflag & CBAUD) == B0 ) { + if ((cflag & CBAUD) != (old_cflag & CBAUD)) { + /* reassert DTR and (maybe) RTS on transition from B0 */ + if ((old_cflag & CBAUD) == B0) { dbg("%s: baud was B0", __func__); #if 0 priv->control_state |= TIOCM_DTR; /* don't set RTS if using hardware flow control */ - if (!(old_cflag & CRTSCTS)) { + if (!(old_cflag & CRTSCTS)) priv->control_state |= TIOCM_RTS; - } mct_u232_set_modem_ctrl(serial, priv->control_state); #endif } } - switch(baud) { - case 0: /* handled below */ - break; - case 1200: - priv->cfg.baudrate = kl5kusb105a_sio_b1200; - break; - case 2400: - priv->cfg.baudrate = kl5kusb105a_sio_b2400; - break; - case 4800: - priv->cfg.baudrate = kl5kusb105a_sio_b4800; - break; - case 9600: - priv->cfg.baudrate = kl5kusb105a_sio_b9600; - break; - case 19200: - priv->cfg.baudrate = kl5kusb105a_sio_b19200; - break; - case 38400: - priv->cfg.baudrate = kl5kusb105a_sio_b38400; - break; - case 57600: - priv->cfg.baudrate = kl5kusb105a_sio_b57600; - break; - case 115200: - priv->cfg.baudrate = kl5kusb105a_sio_b115200; - break; - default: - dbg("KLSI USB->Serial converter:" - " unsupported baudrate request, using default" - " of 9600"); + switch (baud) { + case 0: /* handled below */ + break; + case 1200: + priv->cfg.baudrate = kl5kusb105a_sio_b1200; + break; + case 2400: + priv->cfg.baudrate = kl5kusb105a_sio_b2400; + break; + case 4800: + priv->cfg.baudrate = kl5kusb105a_sio_b4800; + break; + case 9600: + priv->cfg.baudrate = kl5kusb105a_sio_b9600; + break; + case 19200: + priv->cfg.baudrate = kl5kusb105a_sio_b19200; + break; + case 38400: + priv->cfg.baudrate = kl5kusb105a_sio_b38400; + break; + case 57600: + priv->cfg.baudrate = kl5kusb105a_sio_b57600; + break; + case 115200: + priv->cfg.baudrate = kl5kusb105a_sio_b115200; + break; + default: + dbg("KLSI USB->Serial converter:" + " unsupported baudrate request, using default of 9600"); priv->cfg.baudrate = kl5kusb105a_sio_b9600; - baud = 9600; - break; + baud = 9600; + break; } - if ((cflag & CBAUD) == B0 ) { + if ((cflag & CBAUD) == B0) { dbg("%s: baud is B0", __func__); /* Drop RTS and DTR */ /* maybe this should be simulated by sending read @@ -778,7 +775,7 @@ static void klsi_105_set_termios (struct usb_serial_port *port, ; #if 0 priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); - mct_u232_set_modem_ctrl(serial, priv->control_state); + mct_u232_set_modem_ctrl(serial, priv->control_state); #endif } tty_encode_baud_rate(tty, baud, baud); @@ -788,11 +785,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port, switch (cflag & CSIZE) { case CS5: dbg("%s - 5 bits/byte not supported", __func__); - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return ; case CS6: dbg("%s - 6 bits/byte not supported", __func__); - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return ; case CS7: priv->cfg.databits = kl5kusb105a_dtb_7; @@ -811,8 +808,7 @@ static void klsi_105_set_termios (struct usb_serial_port *port, * Update line control register (LCR) */ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) - || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) { - + || (cflag & CSTOPB) != (old_cflag & CSTOPB)) { /* Not currently supported */ tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB); #if 0 @@ -833,20 +829,18 @@ static void klsi_105_set_termios (struct usb_serial_port *port, #endif ; } - /* * Set flow control: well, I do not really now how to handle DTR/RTS. * Just do what we have seen with SniffUSB on Win98. */ - if( (iflag & IXOFF) != (old_iflag & IXOFF) + if ((iflag & IXOFF) != (old_iflag & IXOFF) || (iflag & IXON) != (old_iflag & IXON) - || (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) { - + || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { /* Not currently supported */ tty->termios->c_cflag &= ~CRTSCTS; /* Drop DTR/RTS if no flow control otherwise assert */ #if 0 - if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) ) + if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) priv->control_state |= TIOCM_DTR | TIOCM_RTS; else priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); @@ -854,19 +848,21 @@ static void klsi_105_set_termios (struct usb_serial_port *port, #endif ; } - memcpy (&cfg, &priv->cfg, sizeof(cfg)); - spin_unlock_irqrestore (&priv->lock, flags); - + memcpy(&cfg, &priv->cfg, sizeof(cfg)); + spin_unlock_irqrestore(&priv->lock, flags); + /* now commit changes to device */ klsi_105_chg_port_settings(port, &cfg); } /* klsi_105_set_termios */ #if 0 -static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) +static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; - struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + struct mct_u232_private *priv = + (struct mct_u232_private *)port->private; unsigned char lcr = priv->last_lcr; dbg("%sstate=%d", __func__, break_state); @@ -878,8 +874,9 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) } /* mct_u232_break_ctl */ #endif -static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file) +static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct klsi_105_private *priv = usb_get_serial_port_data(port); unsigned long flags; int rc; @@ -893,18 +890,18 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file) return rc; } - spin_lock_irqsave (&priv->lock, flags); + spin_lock_irqsave(&priv->lock, flags); priv->line_state = line_state; - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - read line state 0x%lx", __func__, line_state); return (int)line_state; } -static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file, - unsigned int set, unsigned int clear) +static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { int retval = -EINVAL; - + dbg("%s", __func__); /* if this ever gets implemented, it should be done something like this: @@ -929,14 +926,16 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file, return retval; } -static void klsi_105_throttle (struct usb_serial_port *port) +static void klsi_105_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); usb_kill_urb(port->read_urb); } -static void klsi_105_unthrottle (struct usb_serial_port *port) +static void klsi_105_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int result; dbg("%s - port %d", __func__, port->number); @@ -950,7 +949,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port) -static int __init klsi_105_init (void) +static int __init klsi_105_init(void) { int retval; retval = usb_serial_register(&kl5kusb105d_device); @@ -969,19 +968,19 @@ failed_usb_serial_register: } -static void __exit klsi_105_exit (void) +static void __exit klsi_105_exit(void) { - usb_deregister (&kl5kusb105d_driver); - usb_serial_deregister (&kl5kusb105d_device); + usb_deregister(&kl5kusb105d_driver); + usb_serial_deregister(&kl5kusb105d_device); } -module_init (klsi_105_init); -module_exit (klsi_105_exit); +module_init(klsi_105_init); +module_exit(klsi_105_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 693f00da7c03..deba28ec77e8 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -1,7 +1,7 @@ /* * KOBIL USB Smart Card Terminal Driver * - * Copyright (C) 2002 KOBIL Systems GmbH + * Copyright (C) 2002 KOBIL Systems GmbH * Author: Thomas Wahrenbruch * * Contact: linuxusb@kobil.de @@ -20,7 +20,7 @@ * * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus * (Adapter K), B1 Professional and KAAN Professional (Adapter B) - * + * * (21/05/2004) tw * Fix bug with P'n'P readers * @@ -44,7 +44,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include <linux/ioctl.h> @@ -68,21 +68,24 @@ static int debug; /* Function prototypes */ -static int kobil_startup (struct usb_serial *serial); -static void kobil_shutdown (struct usb_serial *serial); -static int kobil_open (struct usb_serial_port *port, struct file *filp); -static void kobil_close (struct usb_serial_port *port, struct file *filp); -static int kobil_write (struct usb_serial_port *port, +static int kobil_startup(struct usb_serial *serial); +static void kobil_shutdown(struct usb_serial *serial); +static int kobil_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); -static int kobil_write_room(struct usb_serial_port *port); -static int kobil_ioctl(struct usb_serial_port *port, struct file *file, +static int kobil_write_room(struct tty_struct *tty); +static int kobil_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static int kobil_tiocmget(struct usb_serial_port *port, struct file *file); -static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, +static int kobil_tiocmget(struct tty_struct *tty, struct file *file); +static int kobil_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); -static void kobil_read_int_callback( struct urb *urb ); -static void kobil_write_callback( struct urb *purb ); -static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old); +static void kobil_read_int_callback(struct urb *urb); +static void kobil_write_callback(struct urb *purb); +static void kobil_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); static struct usb_device_id id_table [] = { @@ -94,7 +97,7 @@ static struct usb_device_id id_table [] = { }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver kobil_driver = { .name = "kobil", @@ -131,14 +134,14 @@ static struct usb_serial_driver kobil_device = { struct kobil_private { int write_int_endpoint_address; int read_int_endpoint_address; - unsigned char buf[KOBIL_BUF_LENGTH]; // buffer for the APDU to send - int filled; // index of the last char in buf - int cur_pos; // index of the next char to send in buf + unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */ + int filled; /* index of the last char in buf */ + int cur_pos; /* index of the next char to send in buf */ __u16 device_type; }; -static int kobil_startup (struct usb_serial *serial) +static int kobil_startup(struct usb_serial *serial) { int i; struct kobil_private *priv; @@ -149,20 +152,20 @@ static int kobil_startup (struct usb_serial *serial) struct usb_host_endpoint *endpoint; priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL); - if (!priv){ + if (!priv) return -ENOMEM; - } priv->filled = 0; priv->cur_pos = 0; priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct); - switch (priv->device_type){ + switch (priv->device_type) { case KOBIL_ADAPTER_B_PRODUCT_ID: printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n"); break; case KOBIL_ADAPTER_K_PRODUCT_ID: - printk(KERN_DEBUG "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); + printk(KERN_DEBUG + "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); break; case KOBIL_USBTWIN_PRODUCT_ID: printk(KERN_DEBUG "KOBIL USBTWIN detected\n"); @@ -173,44 +176,48 @@ static int kobil_startup (struct usb_serial *serial) } usb_set_serial_port_data(serial->port[0], priv); - // search for the necessary endpoints + /* search for the necessary endpoints */ pdev = serial->dev; - actconfig = pdev->actconfig; - interface = actconfig->interface[0]; + actconfig = pdev->actconfig; + interface = actconfig->interface[0]; altsetting = interface->cur_altsetting; - endpoint = altsetting->endpoint; - - for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { + endpoint = altsetting->endpoint; + + for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { endpoint = &altsetting->endpoint[i]; if (usb_endpoint_is_int_out(&endpoint->desc)) { - dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress); - priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress; - } + dbg("%s Found interrupt out endpoint. Address: %d", + __func__, endpoint->desc.bEndpointAddress); + priv->write_int_endpoint_address = + endpoint->desc.bEndpointAddress; + } if (usb_endpoint_is_int_in(&endpoint->desc)) { - dbg("%s Found interrupt in endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress); - priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress; - } + dbg("%s Found interrupt in endpoint. Address: %d", + __func__, endpoint->desc.bEndpointAddress); + priv->read_int_endpoint_address = + endpoint->desc.bEndpointAddress; + } } return 0; } -static void kobil_shutdown (struct usb_serial *serial) +static void kobil_shutdown(struct usb_serial *serial) { int i; dbg("%s - port %d", __func__, serial->port[0]->number); - for (i=0; i < serial->num_ports; ++i) { - while (serial->port[i]->open_count > 0) { - kobil_close (serial->port[i], NULL); - } + for (i = 0; i < serial->num_ports; ++i) { + while (serial->port[i]->port.count > 0) + kobil_close(NULL, serial->port[i], NULL); kfree(usb_get_serial_port_data(serial->port[i])); usb_set_serial_port_data(serial->port[i], NULL); } } -static int kobil_open (struct usb_serial_port *port, struct file *filp) +static int kobil_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int result = 0; struct kobil_private *priv; @@ -221,7 +228,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) dbg("%s - port %d", __func__, port->number); priv = usb_get_serial_port_data(port); - // someone sets the dev to 0 if the close method has been called + /* someone sets the dev to 0 if the close method has been called */ port->interrupt_in_urb->dev = port->serial->dev; @@ -229,100 +236,115 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) * the data through, otherwise it is scheduled, and with high * data rates (like with OHCI) data can get lost. */ - port->tty->low_latency = 1; - - // without this, every push_tty_char is echoed :-( - port->tty->termios->c_lflag = 0; - port->tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE); - port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; - port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) - - // allocate memory for transfer buffer + if (tty) { + tty->low_latency = 1; + + /* Default to echo off and other sane device settings */ + tty->termios->c_lflag = 0; + tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | + XCASE); + tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; + /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */ + tty->termios->c_oflag &= ~ONLCR; + } + /* allocate memory for transfer buffer */ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); - if (! transfer_buffer) { + if (!transfer_buffer) return -ENOMEM; - } - - // allocate write_urb - if (!port->write_urb) { - dbg("%s - port %d Allocating port->write_urb", __func__, port->number); - port->write_urb = usb_alloc_urb(0, GFP_KERNEL); + + /* allocate write_urb */ + if (!port->write_urb) { + dbg("%s - port %d Allocating port->write_urb", + __func__, port->number); + port->write_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->write_urb) { - dbg("%s - port %d usb_alloc_urb failed", __func__, port->number); + dbg("%s - port %d usb_alloc_urb failed", + __func__, port->number); kfree(transfer_buffer); return -ENOMEM; } } - // allocate memory for write_urb transfer buffer - port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); - if (! port->write_urb->transfer_buffer) { + /* allocate memory for write_urb transfer buffer */ + port->write_urb->transfer_buffer = + kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); + if (!port->write_urb->transfer_buffer) { kfree(transfer_buffer); usb_free_urb(port->write_urb); port->write_urb = NULL; return -ENOMEM; - } - - // get hardware version - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_GetMisc, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, - SUSBCR_MSC_GetHWVersion, - 0, - transfer_buffer, - transfer_buffer_length, - KOBIL_TIMEOUT + } + + /* get hardware version */ + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_GetMisc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, + SUSBCR_MSC_GetHWVersion, + 0, + transfer_buffer, + transfer_buffer_length, + KOBIL_TIMEOUT + ); + dbg("%s - port %d Send get_HW_version URB returns: %i", + __func__, port->number, result); + dbg("Harware version: %i.%i.%i", + transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]); + + /* get firmware version */ + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_GetMisc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, + SUSBCR_MSC_GetFWVersion, + 0, + transfer_buffer, + transfer_buffer_length, + KOBIL_TIMEOUT + ); + dbg("%s - port %d Send get_FW_version URB returns: %i", + __func__, port->number, result); + dbg("Firmware version: %i.%i.%i", + transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]); + + if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || + priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { + /* Setting Baudrate, Parity and Stopbits */ + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_SetBaudRateParityAndStopBits, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | + SUSBCR_SPASB_1StopBit, + 0, + transfer_buffer, + 0, + KOBIL_TIMEOUT ); - dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result); - dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] ); - - // get firmware version - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_GetMisc, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, - SUSBCR_MSC_GetFWVersion, - 0, - transfer_buffer, - transfer_buffer_length, - KOBIL_TIMEOUT + dbg("%s - port %d Send set_baudrate URB returns: %i", + __func__, port->number, result); + + /* reset all queues */ + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_Misc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + SUSBCR_MSC_ResetAllQueues, + 0, + transfer_buffer, + 0, + KOBIL_TIMEOUT ); - dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result); - dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] ); - - if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { - // Setting Baudrate, Parity and Stopbits - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_SetBaudRateParityAndStopBits, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, - SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | SUSBCR_SPASB_1StopBit, - 0, - transfer_buffer, - 0, - KOBIL_TIMEOUT - ); - dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result); - - // reset all queues - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_Misc, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, - SUSBCR_MSC_ResetAllQueues, - 0, - transfer_buffer, - 0, - KOBIL_TIMEOUT - ); - dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result); + dbg("%s - port %d Send reset_all_queues URB returns: %i", + __func__, port->number, result); } - if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || + if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || + priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { - // start reading (Adapter B 'cause PNP string) - result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); - dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result); + /* start reading (Adapter B 'cause PNP string) */ + result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); + dbg("%s - port %d Send read URB returns: %i", + __func__, port->number, result); } kfree(transfer_buffer); @@ -330,13 +352,14 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) } -static void kobil_close (struct usb_serial_port *port, struct file *filp) +static void kobil_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __func__, port->number); if (port->write_urb) { usb_kill_urb(port->write_urb); - usb_free_urb( port->write_urb ); + usb_free_urb(port->write_urb); port->write_urb = NULL; } usb_kill_urb(port->interrupt_in_urb); @@ -350,7 +373,7 @@ static void kobil_read_int_callback(struct urb *urb) struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; -// char *dbg_data; +/* char *dbg_data; */ dbg("%s - port %d", __func__, port->number); @@ -360,51 +383,53 @@ static void kobil_read_int_callback(struct urb *urb) return; } - tty = port->tty; + tty = port->port.tty; if (urb->actual_length) { - // BEGIN DEBUG + /* BEGIN DEBUG */ /* - dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); + dbg_data = kzalloc((3 * purb->actual_length + 10) + * sizeof(char), GFP_KERNEL); if (! dbg_data) { - return; + return; } - for (i = 0; i < purb->actual_length; i++) { - sprintf(dbg_data +3*i, "%02X ", data[i]); + for (i = 0; i < purb->actual_length; i++) { + sprintf(dbg_data +3*i, "%02X ", data[i]); } - dbg(" <-- %s", dbg_data ); + dbg(" <-- %s", dbg_data); kfree(dbg_data); */ - // END DEBUG + /* END DEBUG */ tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } - - // someone sets the dev to 0 if the close method has been called + /* someone sets the dev to 0 if the close method has been called */ port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); - dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result); + dbg("%s - port %d Send read URB returns: %i", + __func__, port->number, result); } -static void kobil_write_callback( struct urb *purb ) +static void kobil_write_callback(struct urb *purb) { } -static int kobil_write (struct usb_serial_port *port, +static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { int length = 0; int result = 0; int todo = 0; - struct kobil_private * priv; + struct kobil_private *priv; if (count == 0) { - dbg("%s - port %d write request of 0 bytes", __func__, port->number); + dbg("%s - port %d write request of 0 bytes", + __func__, port->number); return 0; } @@ -415,106 +440,113 @@ static int kobil_write (struct usb_serial_port *port, return -ENOMEM; } - // Copy data to buffer - memcpy (priv->buf + priv->filled, buf, count); - - usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled); - + /* Copy data to buffer */ + memcpy(priv->buf + priv->filled, buf, count); + usb_serial_debug_data(debug, &port->dev, __func__, count, + priv->buf + priv->filled); priv->filled = priv->filled + count; - - // only send complete block. TWIN, KAAN SIM and adapter K use the same protocol. - if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || - ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) { - - // stop reading (except TWIN and KAAN SIM) - if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) + /* only send complete block. TWIN, KAAN SIM and adapter K + use the same protocol. */ + if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || + ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) { + /* stop reading (except TWIN and KAAN SIM) */ + if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) + || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID)) usb_kill_urb(port->interrupt_in_urb); todo = priv->filled - priv->cur_pos; - while(todo > 0) { - // max 8 byte in one urb (endpoint size) + while (todo > 0) { + /* max 8 byte in one urb (endpoint size) */ length = (todo < 8) ? todo : 8; - // copy data to transfer buffer - memcpy(port->write_urb->transfer_buffer, priv->buf + priv->cur_pos, length ); - usb_fill_int_urb( port->write_urb, - port->serial->dev, - usb_sndintpipe(port->serial->dev, priv->write_int_endpoint_address), - port->write_urb->transfer_buffer, - length, - kobil_write_callback, - port, - 8 - ); + /* copy data to transfer buffer */ + memcpy(port->write_urb->transfer_buffer, + priv->buf + priv->cur_pos, length); + usb_fill_int_urb(port->write_urb, + port->serial->dev, + usb_sndintpipe(port->serial->dev, + priv->write_int_endpoint_address), + port->write_urb->transfer_buffer, + length, + kobil_write_callback, + port, + 8 + ); priv->cur_pos = priv->cur_pos + length; - result = usb_submit_urb( port->write_urb, GFP_NOIO ); - dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result); + result = usb_submit_urb(port->write_urb, GFP_NOIO); + dbg("%s - port %d Send write URB returns: %i", + __func__, port->number, result); todo = priv->filled - priv->cur_pos; - if (todo > 0) { + if (todo > 0) msleep(24); - } + } - } // end while - priv->filled = 0; priv->cur_pos = 0; - // someone sets the dev to 0 if the close method has been called + /* someone sets the dev to 0 if the close method + has been called */ port->interrupt_in_urb->dev = port->serial->dev; - - // start reading (except TWIN and KAAN SIM) - if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) { - // someone sets the dev to 0 if the close method has been called + + /* start reading (except TWIN and KAAN SIM) */ + if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || + priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { + /* someone sets the dev to 0 if the close method has + been called */ port->interrupt_in_urb->dev = port->serial->dev; - - result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO ); - dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result); + + result = usb_submit_urb(port->interrupt_in_urb, + GFP_NOIO); + dbg("%s - port %d Send read URB returns: %i", + __func__, port->number, result); } } return count; } -static int kobil_write_room (struct usb_serial_port *port) +static int kobil_write_room(struct tty_struct *tty) { - //dbg("%s - port %d", __func__, port->number); + /* dbg("%s - port %d", __func__, port->number); */ + /* FIXME */ return 8; } -static int kobil_tiocmget(struct usb_serial_port *port, struct file *file) +static int kobil_tiocmget(struct tty_struct *tty, struct file *file) { - struct kobil_private * priv; + struct usb_serial_port *port = tty->driver_data; + struct kobil_private *priv; int result; unsigned char *transfer_buffer; int transfer_buffer_length = 8; priv = usb_get_serial_port_data(port); - if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) { - // This device doesn't support ioctl calls + if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID + || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { + /* This device doesn't support ioctl calls */ return -EINVAL; } - // allocate memory for transfer buffer + /* allocate memory for transfer buffer */ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); - if (!transfer_buffer) { + if (!transfer_buffer) return -ENOMEM; - } - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_GetStatusLineState, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, - 0, - 0, - transfer_buffer, - transfer_buffer_length, - KOBIL_TIMEOUT); - - dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_GetStatusLineState, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, + 0, + 0, + transfer_buffer, + transfer_buffer_length, + KOBIL_TIMEOUT); + + dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", __func__, port->number, result, transfer_buffer[0]); result = 0; @@ -524,10 +556,11 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file) return result; } -static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, +static int kobil_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - struct kobil_private * priv; + struct usb_serial_port *port = tty->driver_data; + struct kobil_private *priv; int result; int dtr = 0; int rts = 0; @@ -536,16 +569,16 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, /* FIXME: locking ? */ priv = usb_get_serial_port_data(port); - if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) { - // This device doesn't support ioctl calls + if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID + || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { + /* This device doesn't support ioctl calls */ return -EINVAL; } - // allocate memory for transfer buffer + /* allocate memory for transfer buffer */ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); - if (! transfer_buffer) { + if (!transfer_buffer) return -ENOMEM; - } if (set & TIOCM_RTS) rts = 1; @@ -558,66 +591,77 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) { if (dtr != 0) - dbg("%s - port %d Setting DTR", __func__, port->number); + dbg("%s - port %d Setting DTR", + __func__, port->number); else - dbg("%s - port %d Clearing DTR", __func__, port->number); - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_SetStatusLinesOrQueues, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, - ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR), - 0, - transfer_buffer, - 0, - KOBIL_TIMEOUT); + dbg("%s - port %d Clearing DTR", + __func__, port->number); + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_SetStatusLinesOrQueues, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR), + 0, + transfer_buffer, + 0, + KOBIL_TIMEOUT); } else { if (rts != 0) - dbg("%s - port %d Setting RTS", __func__, port->number); + dbg("%s - port %d Setting RTS", + __func__, port->number); else - dbg("%s - port %d Clearing RTS", __func__, port->number); - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_SetStatusLinesOrQueues, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, - ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS), - 0, - transfer_buffer, - 0, - KOBIL_TIMEOUT); + dbg("%s - port %d Clearing RTS", + __func__, port->number); + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_SetStatusLinesOrQueues, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS), + 0, + transfer_buffer, + 0, + KOBIL_TIMEOUT); } - dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result); + dbg("%s - port %d Send set_status_line URB returns: %i", + __func__, port->number, result); kfree(transfer_buffer); return (result < 0) ? result : 0; } -static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old) +static void kobil_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old) { - struct kobil_private * priv; + struct kobil_private *priv; int result; unsigned short urb_val = 0; - int c_cflag = port->tty->termios->c_cflag; + int c_cflag = tty->termios->c_cflag; speed_t speed; - void * settings; + void *settings; priv = usb_get_serial_port_data(port); - if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) - // This device doesn't support ioctl calls + if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || + priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { + /* This device doesn't support ioctl calls */ + *tty->termios = *old; return; + } - switch (speed = tty_get_baud_rate(port->tty)) { - case 1200: - urb_val = SUSBCR_SBR_1200; - break; - default: - speed = 9600; - case 9600: - urb_val = SUSBCR_SBR_9600; - break; + speed = tty_get_baud_rate(tty); + switch (speed) { + case 1200: + urb_val = SUSBCR_SBR_1200; + break; + default: + speed = 9600; + case 9600: + urb_val = SUSBCR_SBR_9600; + break; } - urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit; + urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : + SUSBCR_SPASB_1StopBit; settings = kzalloc(50, GFP_KERNEL); - if (! settings) + if (!settings) return; sprintf(settings, "%d ", speed); @@ -634,66 +678,69 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old urb_val |= SUSBCR_SPASB_NoParity; strcat(settings, "No Parity"); } - port->tty->termios->c_cflag &= ~CMSPAR; - tty_encode_baud_rate(port->tty, speed, speed); - - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_SetBaudRateParityAndStopBits, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, - urb_val, - 0, - settings, - 0, - KOBIL_TIMEOUT + tty->termios->c_cflag &= ~CMSPAR; + tty_encode_baud_rate(tty, speed, speed); + + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_SetBaudRateParityAndStopBits, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + urb_val, + 0, + settings, + 0, + KOBIL_TIMEOUT ); kfree(settings); } -static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +static int kobil_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { - struct kobil_private * priv = usb_get_serial_port_data(port); + struct usb_serial_port *port = tty->driver_data; + struct kobil_private *priv = usb_get_serial_port_data(port); unsigned char *transfer_buffer; int transfer_buffer_length = 8; int result; - if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) - // This device doesn't support ioctl calls - return 0; + if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || + priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) + /* This device doesn't support ioctl calls */ + return -ENOIOCTLCMD; switch (cmd) { - case TCFLSH: // 0x540B + case TCFLSH: transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL); - if (! transfer_buffer) - return -ENOBUFS; - - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), - SUSBCRequest_Misc, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, - SUSBCR_MSC_ResetAllQueues, - 0, - NULL,//transfer_buffer, - 0, - KOBIL_TIMEOUT + if (!transfer_buffer) + return -ENOBUFS; + + result = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + SUSBCRequest_Misc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + SUSBCR_MSC_ResetAllQueues, + 0, + NULL, /* transfer_buffer, */ + 0, + KOBIL_TIMEOUT ); - + dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result); kfree(transfer_buffer); - return (result < 0) ? -EFAULT : 0; + return (result < 0) ? -EIO: 0; default: return -ENOIOCTLCMD; } } -static int __init kobil_init (void) +static int __init kobil_init(void) { int retval; retval = usb_serial_register(&kobil_device); if (retval) goto failed_usb_serial_register; retval = usb_register(&kobil_driver); - if (retval) + if (retval) goto failed_usb_register; info(DRIVER_VERSION " " DRIVER_AUTHOR); @@ -707,18 +754,18 @@ failed_usb_serial_register: } -static void __exit kobil_exit (void) +static void __exit kobil_exit(void) { - usb_deregister (&kobil_driver); - usb_serial_deregister (&kobil_device); + usb_deregister(&kobil_driver); + usb_serial_deregister(&kobil_device); } module_init(kobil_init); module_exit(kobil_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE( "GPL" ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 5fc2cef30e39..0ded8bd6ec85 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -33,10 +33,11 @@ * - Fixed an endianess problem with the baudrate selection for PowerPC. * * 06-Dec-2001 Martin Hamilton <martinh@gnu.org> - * Added support for the Belkin F5U109 DB9 adaptor + * - Added support for the Belkin F5U109 DB9 adaptor * * 30-May-2001 Greg Kroah-Hartman - * switched from using spinlock to a semaphore, which fixes lots of problems. + * - switched from using spinlock to a semaphore, which fixes lots of + * problems. * * 04-May-2001 Stelian Pop * - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes @@ -49,7 +50,7 @@ * 08-Apr-2001 gb * - Identify version on module load. * - * 06-Jan-2001 Cornel Ciocirlan + * 06-Jan-2001 Cornel Ciocirlan * - Added support for Sitecom U232-P25 model (Product Id 0x0230) * - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200) * @@ -59,8 +60,8 @@ * (lots of things will change if/when the usb-serial core changes to * handle these issues. * - * 27-Nov-2000 Wolfgang Grandegger - * A version for kernel 2.4.0-test10 released to the Linux community + * 27-Nov-2000 Wolfgang Grandegge + * A version for kernel 2.4.0-test10 released to the Linux community * (via linux-usb-devel). */ @@ -73,7 +74,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "mct_u232.h" @@ -90,28 +91,21 @@ static int debug; /* * Function prototypes */ -static int mct_u232_startup (struct usb_serial *serial); -static void mct_u232_shutdown (struct usb_serial *serial); -static int mct_u232_open (struct usb_serial_port *port, - struct file *filp); -static void mct_u232_close (struct usb_serial_port *port, - struct file *filp); -static void mct_u232_read_int_callback (struct urb *urb); -static void mct_u232_set_termios (struct usb_serial_port *port, - struct ktermios * old); -static int mct_u232_ioctl (struct usb_serial_port *port, - struct file * file, - unsigned int cmd, - unsigned long arg); -static void mct_u232_break_ctl (struct usb_serial_port *port, - int break_state ); -static int mct_u232_tiocmget (struct usb_serial_port *port, - struct file *file); -static int mct_u232_tiocmset (struct usb_serial_port *port, - struct file *file, unsigned int set, - unsigned int clear); -static void mct_u232_throttle (struct usb_serial_port *port); -static void mct_u232_unthrottle (struct usb_serial_port *port); +static int mct_u232_startup(struct usb_serial *serial); +static void mct_u232_shutdown(struct usb_serial *serial); +static int mct_u232_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void mct_u232_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void mct_u232_read_int_callback(struct urb *urb); +static void mct_u232_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); +static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file); +static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static void mct_u232_throttle(struct tty_struct *tty); +static void mct_u232_unthrottle(struct tty_struct *tty); /* @@ -125,7 +119,7 @@ static struct usb_device_id id_table_combined [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver mct_u232_driver = { .name = "mct_u232", @@ -149,7 +143,6 @@ static struct usb_serial_driver mct_u232_device = { .throttle = mct_u232_throttle, .unthrottle = mct_u232_unthrottle, .read_int_callback = mct_u232_read_int_callback, - .ioctl = mct_u232_ioctl, .set_termios = mct_u232_set_termios, .break_ctl = mct_u232_break_ctl, .tiocmget = mct_u232_tiocmget, @@ -180,23 +173,34 @@ struct mct_u232_private { * Later day 2.6.0-test kernels have new baud rates like B230400 which * we do not know how to support. We ignore them for the moment. */ -static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result) +static int mct_u232_calculate_baud_rate(struct usb_serial *serial, + speed_t value, speed_t *result) { *result = value; if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID - || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { + || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { switch (value) { - case 300: return 0x01; - case 600: return 0x02; /* this one not tested */ - case 1200: return 0x03; - case 2400: return 0x04; - case 4800: return 0x06; - case 9600: return 0x08; - case 19200: return 0x09; - case 38400: return 0x0a; - case 57600: return 0x0b; - case 115200: return 0x0c; + case 300: + return 0x01; + case 600: + return 0x02; /* this one not tested */ + case 1200: + return 0x03; + case 2400: + return 0x04; + case 4800: + return 0x06; + case 9600: + return 0x08; + case 19200: + return 0x09; + case 38400: + return 0x0a; + case 57600: + return 0x0b; + case 115200: + return 0x0c; default: *result = 9600; return 0x08; @@ -224,26 +228,27 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value } } -static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port, - speed_t value) +static int mct_u232_set_baud_rate(struct tty_struct *tty, + struct usb_serial *serial, struct usb_serial_port *port, speed_t value) { __le32 divisor; - int rc; - unsigned char zero_byte = 0; - unsigned char cts_enable_byte = 0; - speed_t speed; - - divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed)); - - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - MCT_U232_SET_BAUD_RATE_REQUEST, - MCT_U232_SET_REQUEST_TYPE, - 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, - WDR_TIMEOUT); + int rc; + unsigned char zero_byte = 0; + unsigned char cts_enable_byte = 0; + speed_t speed; + + divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, + &speed)); + + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + MCT_U232_SET_BAUD_RATE_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, + WDR_TIMEOUT); if (rc < 0) /*FIXME: What value speed results */ err("Set BAUD RATE %d failed (error = %d)", value, rc); else - tty_encode_baud_rate(port->tty, speed, speed); + tty_encode_baud_rate(tty, speed, speed); dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor); /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which @@ -258,55 +263,55 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_p whether data will be transmitted to a device which is not asserting the 'CTS' signal. If the second message's data byte is zero, data will be transmitted even if 'CTS' is not asserted (i.e. no hardware - flow control). if the second message's data byte is nonzero (a value - of 1 is used by this driver), data will not be transmitted to a device - which is not asserting 'CTS'. + flow control). if the second message's data byte is nonzero (a + value of 1 is used by this driver), data will not be transmitted to + a device which is not asserting 'CTS'. */ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - MCT_U232_SET_UNKNOWN1_REQUEST, - MCT_U232_SET_REQUEST_TYPE, - 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, - WDR_TIMEOUT); + MCT_U232_SET_UNKNOWN1_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, + WDR_TIMEOUT); if (rc < 0) - err("Sending USB device request code %d failed (error = %d)", + err("Sending USB device request code %d failed (error = %d)", MCT_U232_SET_UNKNOWN1_REQUEST, rc); - if (port && C_CRTSCTS(port->tty)) { + if (port && C_CRTSCTS(tty)) cts_enable_byte = 1; - } - dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte); + dbg("set_baud_rate: send second control message, data = %02X", + cts_enable_byte); rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - MCT_U232_SET_CTS_REQUEST, - MCT_U232_SET_REQUEST_TYPE, - 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE, - WDR_TIMEOUT); + MCT_U232_SET_CTS_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE, + WDR_TIMEOUT); if (rc < 0) - err("Sending USB device request code %d failed (error = %d)", - MCT_U232_SET_CTS_REQUEST, rc); + err("Sending USB device request code %d failed (error = %d)", + MCT_U232_SET_CTS_REQUEST, rc); - return rc; + return rc; } /* mct_u232_set_baud_rate */ static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) { - int rc; - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - MCT_U232_SET_LINE_CTRL_REQUEST, - MCT_U232_SET_REQUEST_TYPE, - 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE, - WDR_TIMEOUT); + int rc; + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + MCT_U232_SET_LINE_CTRL_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE, + WDR_TIMEOUT); if (rc < 0) err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc); dbg("set_line_ctrl: 0x%x", lcr); - return rc; + return rc; } /* mct_u232_set_line_ctrl */ static int mct_u232_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state) { - int rc; + int rc; unsigned char mcr = MCT_U232_MCR_NONE; if (control_state & TIOCM_DTR) @@ -314,37 +319,39 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial, if (control_state & TIOCM_RTS) mcr |= MCT_U232_MCR_RTS; - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - MCT_U232_SET_MODEM_CTRL_REQUEST, - MCT_U232_SET_REQUEST_TYPE, - 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE, - WDR_TIMEOUT); + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + MCT_U232_SET_MODEM_CTRL_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE, + WDR_TIMEOUT); if (rc < 0) err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc); dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); - return rc; + return rc; } /* mct_u232_set_modem_ctrl */ -static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr) +static int mct_u232_get_modem_stat(struct usb_serial *serial, + unsigned char *msr) { - int rc; - rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - MCT_U232_GET_MODEM_STAT_REQUEST, - MCT_U232_GET_REQUEST_TYPE, - 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE, - WDR_TIMEOUT); + int rc; + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + MCT_U232_GET_MODEM_STAT_REQUEST, + MCT_U232_GET_REQUEST_TYPE, + 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE, + WDR_TIMEOUT); if (rc < 0) { err("Get MODEM STATus failed (error = %d)", rc); *msr = 0; } dbg("get_modem_stat: 0x%x", *msr); - return rc; + return rc; } /* mct_u232_get_modem_stat */ -static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr) +static void mct_u232_msr_to_state(unsigned int *control_state, + unsigned char msr) { - /* Translate Control Line states */ + /* Translate Control Line states */ if (msr & MCT_U232_MSR_DSR) *control_state |= TIOCM_DSR; else @@ -361,14 +368,14 @@ static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr *control_state |= TIOCM_CD; else *control_state &= ~TIOCM_CD; - dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state); + dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state); } /* mct_u232_msr_to_state */ /* * Driver's tty interface functions */ -static int mct_u232_startup (struct usb_serial *serial) +static int mct_u232_startup(struct usb_serial *serial) { struct mct_u232_private *priv; struct usb_serial_port *port, *rport; @@ -390,18 +397,18 @@ static int mct_u232_startup (struct usb_serial *serial) rport->interrupt_in_urb = NULL; port->read_urb->context = port; - return (0); + return 0; } /* mct_u232_startup */ -static void mct_u232_shutdown (struct usb_serial *serial) +static void mct_u232_shutdown(struct usb_serial *serial) { struct mct_u232_private *priv; int i; - + dbg("%s", __func__); - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) { /* My special items, the standard routines free my urbs */ priv = usb_get_serial_port_data(serial->port[i]); if (priv) { @@ -411,7 +418,8 @@ static void mct_u232_shutdown (struct usb_serial *serial) } } /* mct_u232_shutdown */ -static int mct_u232_open (struct usb_serial_port *port, struct file *filp) +static int mct_u232_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); @@ -428,21 +436,22 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp) * it seems to be able to accept only 16 bytes (and that's what * SniffUSB says too...) */ - if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID) + if (le16_to_cpu(serial->dev->descriptor.idProduct) + == MCT_U232_SITECOM_PID) port->bulk_out_size = 16; - /* Do a defined restart: the normal serial device seems to + /* Do a defined restart: the normal serial device seems to * always turn on DTR and RTS here, so do the same. I'm not * sure if this is really necessary. But it should not harm * either. */ spin_lock_irqsave(&priv->lock, flags); - if (port->tty->termios->c_cflag & CBAUD) + if (tty && (tty->termios->c_cflag & CBAUD)) priv->control_state = TIOCM_DTR | TIOCM_RTS; else priv->control_state = 0; - - priv->last_lcr = (MCT_U232_DATA_BITS_8 | + + priv->last_lcr = (MCT_U232_DATA_BITS_8 | MCT_U232_PARITY_NONE | MCT_U232_STOP_BITS_1); control_state = priv->control_state; @@ -481,15 +490,16 @@ error: } /* mct_u232_open */ -static void mct_u232_close (struct usb_serial_port *port, struct file *filp) +static void mct_u232_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { unsigned int c_cflag; unsigned int control_state; struct mct_u232_private *priv = usb_get_serial_port_data(port); dbg("%s port %d", __func__, port->number); - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; + if (tty) { + c_cflag = tty->termios->c_cflag; mutex_lock(&port->serial->disc_mutex); if (c_cflag & HUPCL && !port->serial->disconnected) { /* drop DTR and RTS */ @@ -512,7 +522,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp) } /* mct_u232_close */ -static void mct_u232_read_int_callback (struct urb *urb) +static void mct_u232_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct mct_u232_private *priv = usb_get_serial_port_data(port); @@ -545,36 +555,34 @@ static void mct_u232_read_int_callback (struct urb *urb) return; } - dbg("%s - port %d", __func__, port->number); - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + dbg("%s - port %d", __func__, port->number); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); /* * Work-a-round: handle the 'usual' bulk-in pipe here */ if (urb->transfer_buffer_length > 2) { - int i; - tty = port->tty; + tty = port->port.tty; if (urb->actual_length) { - for (i = 0; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } + tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } goto exit; } - + /* * The interrupt-in pipe signals exceptional conditions (modem line * signal changes and errors). data[0] holds MSR, data[1] holds LSR. */ spin_lock_irqsave(&priv->lock, flags); priv->last_msr = data[MCT_U232_MSR_INDEX]; - + /* Record Control Line states */ mct_u232_msr_to_state(&priv->control_state, priv->last_msr); #if 0 - /* Not yet handled. See belin_sa.c for further information */ + /* Not yet handled. See belkin_sa.c for further information */ /* Now to report any errors */ priv->last_lsr = data[MCT_U232_LSR_INDEX]; /* @@ -583,7 +591,7 @@ static void mct_u232_read_int_callback (struct urb *urb) * to look in to this before committing any code. */ if (priv->last_lsr & MCT_U232_LSR_ERR) { - tty = port->tty; + tty = port->port.tty; /* Overrun Error */ if (priv->last_lsr & MCT_U232_LSR_OE) { } @@ -600,18 +608,19 @@ static void mct_u232_read_int_callback (struct urb *urb) #endif spin_unlock_irqrestore(&priv->lock, flags); exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err ("%s - usb_submit_urb failed with result %d", + err("%s - usb_submit_urb failed with result %d", __func__, retval); } /* mct_u232_read_int_callback */ -static void mct_u232_set_termios (struct usb_serial_port *port, - struct ktermios *old_termios) +static void mct_u232_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); - struct ktermios *termios = port->tty->termios; + struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; unsigned long flags; @@ -631,20 +640,20 @@ static void mct_u232_set_termios (struct usb_serial_port *port, * Premature optimization is the root of all evil. */ - /* reassert DTR and RTS on transition from B0 */ + /* reassert DTR and RTS on transition from B0 */ if ((old_cflag & CBAUD) == B0) { dbg("%s: baud was B0", __func__); control_state |= TIOCM_DTR | TIOCM_RTS; mct_u232_set_modem_ctrl(serial, control_state); } - mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty)); + mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty)); - if ((cflag & CBAUD) == B0 ) { + if ((cflag & CBAUD) == B0) { dbg("%s: baud is B0", __func__); /* Drop RTS and DTR */ control_state &= ~(TIOCM_DTR | TIOCM_RTS); - mct_u232_set_modem_ctrl(serial, control_state); + mct_u232_set_modem_ctrl(serial, control_state); } /* @@ -689,8 +698,9 @@ static void mct_u232_set_termios (struct usb_serial_port *port, spin_unlock_irqrestore(&priv->lock, flags); } /* mct_u232_set_termios */ -static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) +static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned char lcr; @@ -709,12 +719,13 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) } /* mct_u232_break_ctl */ -static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file) +static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned int control_state; unsigned long flags; - + dbg("%s", __func__); spin_lock_irqsave(&priv->lock, flags); @@ -724,14 +735,15 @@ static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file) return control_state; } -static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file, +static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned int control_state; unsigned long flags; - + dbg("%s", __func__); spin_lock_irqsave(&priv->lock, flags); @@ -751,77 +763,50 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file, return mct_u232_set_modem_ctrl(serial, control_state); } -static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, - unsigned int cmd, unsigned long arg) -{ - dbg("%scmd=0x%x", __func__, cmd); - - /* Based on code from acm.c and others */ - switch (cmd) { - case TIOCMIWAIT: - /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ - /* TODO */ - return( 0 ); - - case TIOCGICOUNT: - /* return count of modemline transitions */ - /* TODO */ - return 0; - - default: - dbg("%s: arg not supported - 0x%04x", __func__,cmd); - return(-ENOIOCTLCMD); - break; - } - return 0; -} /* mct_u232_ioctl */ - -static void mct_u232_throttle (struct usb_serial_port *port) +static void mct_u232_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int control_state; - struct tty_struct *tty; - tty = port->tty; dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); priv->rx_flags |= THROTTLED; if (C_CRTSCTS(tty)) { - priv->control_state &= ~TIOCM_RTS; - control_state = priv->control_state; - spin_unlock_irqrestore(&priv->lock, flags); - (void) mct_u232_set_modem_ctrl(port->serial, control_state); + priv->control_state &= ~TIOCM_RTS; + control_state = priv->control_state; + spin_unlock_irqrestore(&priv->lock, flags); + (void) mct_u232_set_modem_ctrl(port->serial, control_state); } else { - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } } -static void mct_u232_unthrottle (struct usb_serial_port *port) +static void mct_u232_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int control_state; - struct tty_struct *tty; dbg("%s - port %d", __func__, port->number); - tty = port->tty; spin_lock_irqsave(&priv->lock, flags); if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) { - priv->rx_flags &= ~THROTTLED; - priv->control_state |= TIOCM_RTS; - control_state = priv->control_state; - spin_unlock_irqrestore(&priv->lock, flags); - (void) mct_u232_set_modem_ctrl(port->serial, control_state); + priv->rx_flags &= ~THROTTLED; + priv->control_state |= TIOCM_RTS; + control_state = priv->control_state; + spin_unlock_irqrestore(&priv->lock, flags); + (void) mct_u232_set_modem_ctrl(port->serial, control_state); } else { - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } } -static int __init mct_u232_init (void) +static int __init mct_u232_init(void) { int retval; retval = usb_serial_register(&mct_u232_device); @@ -839,18 +824,17 @@ failed_usb_serial_register: } -static void __exit mct_u232_exit (void) +static void __exit mct_u232_exit(void) { - usb_deregister (&mct_u232_driver); - usb_serial_deregister (&mct_u232_device); + usb_deregister(&mct_u232_driver); + usb_serial_deregister(&mct_u232_device); } - -module_init (mct_u232_init); +module_init(mct_u232_init); module_exit(mct_u232_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 50f1fe263338..7c4917d77c0a 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -33,7 +33,7 @@ #include <linux/serial_reg.h> #include <linux/usb.h> #include <linux/usb/serial.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> /* @@ -64,8 +64,7 @@ #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ /* This structure holds all of the local port information */ -struct moschip_port -{ +struct moschip_port { __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ __u8 shadowMSR; /* last MSR value received */ @@ -76,8 +75,7 @@ struct moschip_port }; /* This structure holds all of the individual serial device information */ -struct moschip_serial -{ +struct moschip_serial { int interrupt_started; }; @@ -88,7 +86,7 @@ static int debug; #define MOSCHIP_DEVICE_ID_7715 0x7715 static struct usb_device_id moschip_port_id_table [] = { - { USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) }, + { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) }, { } /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, moschip_port_id_table); @@ -108,7 +106,7 @@ static void mos7720_interrupt_callback(struct urb *urb) __u8 sp1; __u8 sp2; - dbg("%s"," : Entering\n"); + dbg("%s", " : Entering\n"); switch (status) { case 0: @@ -208,7 +206,7 @@ static void mos7720_bulk_in_callback(struct urb *urb) mos7720_port = urb->context; if (!mos7720_port) { - dbg("%s","NULL mos7720_port pointer \n"); + dbg("%s", "NULL mos7720_port pointer \n"); return ; } @@ -218,7 +216,7 @@ static void mos7720_bulk_in_callback(struct urb *urb) data = urb->transfer_buffer; - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); @@ -264,7 +262,7 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) dbg("Entering ........."); - tty = mos7720_port->port->tty; + tty = mos7720_port->port->port.tty; if (tty && mos7720_port->open) tty_wakeup(tty); @@ -284,17 +282,16 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, __u16 size = 0x0000; if (value < MOS_MAX_PORT) { - if (product == MOSCHIP_DEVICE_ID_7715) { + if (product == MOSCHIP_DEVICE_ID_7715) value = value*0x100+0x100; - } else { + else value = value*0x100+0x200; - } } else { value = 0x0000; if ((product == MOSCHIP_DEVICE_ID_7715) && (index != 0x08)) { dbg("serial->product== MOSCHIP_DEVICE_ID_7715"); - //index = 0x01 ; + /* index = 0x01 ; */ } } @@ -308,19 +305,20 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, request = (__u8)MOS_READ; requesttype = (__u8)0xC0; size = 0x01; - pipe = usb_rcvctrlpipe(serial->dev,0); + pipe = usb_rcvctrlpipe(serial->dev, 0); } status = usb_control_msg(serial->dev, pipe, request, requesttype, value, index, data, size, MOS_WDR_TIMEOUT); if (status < 0) - dbg("Command Write failed Value %x index %x\n",value,index); + dbg("Command Write failed Value %x index %x\n", value, index); return status; } -static int mos7720_open(struct usb_serial_port *port, struct file * filp) +static int mos7720_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial; struct usb_serial_port *port0; @@ -351,7 +349,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) /* Initialising the write urb pool */ for (j = 0; j < NUM_URBS; ++j) { - urb = usb_alloc_urb(0,GFP_KERNEL); + urb = usb_alloc_urb(0, GFP_KERNEL); mos7720_port->write_urb_pool[j] = urb; if (urb == NULL) { @@ -385,7 +383,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) */ port_number = port->number - port->serial->minor; send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data); - dbg("SS::%p LSR:%x\n",mos7720_port, data); + dbg("SS::%p LSR:%x\n", mos7720_port, data); dbg("Check:Sending Command .........."); @@ -402,10 +400,10 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) data = 0xCF; send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); data = 0x03; - mos7720_port->shadowLCR = data; + mos7720_port->shadowLCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); data = 0x0b; - mos7720_port->shadowMCR = data; + mos7720_port->shadowMCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); data = 0x0b; send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); @@ -420,7 +418,8 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) data = 0x03; send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); data = 0x00; - send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); + send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, + port_number + 1, &data); */ data = 0x00; send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); @@ -429,28 +428,26 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); data = 0x83; - mos7720_port->shadowLCR = data; + mos7720_port->shadowLCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); data = 0x0c; send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); data = 0x00; send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); data = 0x03; - mos7720_port->shadowLCR = data; + mos7720_port->shadowLCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); data = 0x0c; send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); data = 0x0c; send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); -//Matrix - /* force low_latency on so that our tty_push actually forces * * the data through,otherwise it is scheduled, and with * * high data rates (like with OHCI) data can get lost. */ - if (port->tty) - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; /* see if we've set up our endpoint info yet * * (can't set it up in mos7720_startup as the * @@ -465,15 +462,15 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) /* set up our interrupt urb */ usb_fill_int_urb(port0->interrupt_in_urb, serial->dev, - usb_rcvintpipe(serial->dev, - port->interrupt_in_endpointAddress), - port0->interrupt_in_buffer, - port0->interrupt_in_urb->transfer_buffer_length, - mos7720_interrupt_callback, mos7720_port, - port0->interrupt_in_urb->interval); + usb_rcvintpipe(serial->dev, + port->interrupt_in_endpointAddress), + port0->interrupt_in_buffer, + port0->interrupt_in_urb->transfer_buffer_length, + mos7720_interrupt_callback, mos7720_port, + port0->interrupt_in_urb->interval); /* start interrupt read for this mos7720 this interrupt * - * will continue as long as the mos7720 is connected */ + * will continue as long as the mos7720 is connected */ dbg("Submit URB over !!!"); response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL); if (response) @@ -485,14 +482,14 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) /* set up our bulk in urb */ usb_fill_bulk_urb(port->read_urb, serial->dev, usb_rcvbulkpipe(serial->dev, - port->bulk_in_endpointAddress), + port->bulk_in_endpointAddress), port->bulk_in_buffer, port->read_urb->transfer_buffer_length, mos7720_bulk_in_callback, mos7720_port); response = usb_submit_urb(port->read_urb, GFP_KERNEL); if (response) - dev_err(&port->dev, - "%s - Error %d submitting read urb\n", __func__, response); + dev_err(&port->dev, "%s - Error %d submitting read urb\n", + __func__, response); /* initialize our icount structure */ memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount)); @@ -515,8 +512,9 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) * system, * Otherwise we return a negative error number. */ -static int mos7720_chars_in_buffer(struct usb_serial_port *port) +static int mos7720_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int i; int chars = 0; struct moschip_port *mos7720_port; @@ -530,14 +528,16 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port) } for (i = 0; i < NUM_URBS; ++i) { - if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS) + if (mos7720_port->write_urb_pool[i] && + mos7720_port->write_urb_pool[i]->status == -EINPROGRESS) chars += URB_TRANSFER_BUFFER_SIZE; } dbg("%s - returns %d", __func__, chars); return chars; } -static void mos7720_close(struct usb_serial_port *port, struct file *filp) +static void mos7720_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial; struct moschip_port *mos7720_port; @@ -575,12 +575,12 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp) * been disconnected */ if (!serial->disconnected) { data = 0x00; - send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, - 0x04, &data); + send_mos_cmd(serial, MOS_WRITE, + port->number - port->serial->minor, 0x04, &data); data = 0x00; - send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, - 0x01, &data); + send_mos_cmd(serial, MOS_WRITE, + port->number - port->serial->minor, 0x01, &data); } mutex_unlock(&serial->disc_mutex); mos7720_port->open = 0; @@ -588,9 +588,10 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp) dbg("Leaving %s", __func__); } -static void mos7720_break(struct usb_serial_port *port, int break_state) +static void mos7720_break(struct tty_struct *tty, int break_state) { - unsigned char data; + struct usb_serial_port *port = tty->driver_data; + unsigned char data; struct usb_serial *serial; struct moschip_port *mos7720_port; @@ -621,8 +622,9 @@ static void mos7720_break(struct usb_serial_port *port, int break_state) * If successful, we return the amount of room that we have for this port * Otherwise we return a negative error number. */ -static int mos7720_write_room(struct usb_serial_port *port) +static int mos7720_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7720_port; int room = 0; int i; @@ -637,7 +639,8 @@ static int mos7720_write_room(struct usb_serial_port *port) /* FIXME: Locking */ for (i = 0; i < NUM_URBS; ++i) { - if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) + if (mos7720_port->write_urb_pool[i] && + mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) room += URB_TRANSFER_BUFFER_SIZE; } @@ -645,8 +648,8 @@ static int mos7720_write_room(struct usb_serial_port *port) return room; } -static int mos7720_write(struct usb_serial_port *port, - const unsigned char *data, int count) +static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *data, int count) { int status; int i; @@ -672,9 +675,10 @@ static int mos7720_write(struct usb_serial_port *port, urb = NULL; for (i = 0; i < NUM_URBS; ++i) { - if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) { + if (mos7720_port->write_urb_pool[i] && + mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) { urb = mos7720_port->write_urb_pool[i]; - dbg("URB:%d",i); + dbg("URB:%d", i); break; } } @@ -692,7 +696,7 @@ static int mos7720_write(struct usb_serial_port *port, goto exit; } } - transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE); + transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); memcpy(urb->transfer_buffer, current_position, transfer_size); usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, @@ -701,12 +705,12 @@ static int mos7720_write(struct usb_serial_port *port, /* fill urb with data and submit */ usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), + port->bulk_out_endpointAddress), urb->transfer_buffer, transfer_size, mos7720_bulk_out_data_callback, mos7720_port); /* send it down the pipe */ - status = usb_submit_urb(urb,GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { err("%s - usb_submit_urb(write bulk) failed with status = %d", __func__, status); @@ -719,10 +723,10 @@ exit: return bytes_sent; } -static void mos7720_throttle(struct usb_serial_port *port) +static void mos7720_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7720_port; - struct tty_struct *tty; int status; dbg("%s- port %d\n", __func__, port->number); @@ -739,16 +743,10 @@ static void mos7720_throttle(struct usb_serial_port *port) dbg("%s: Entering ..........", __func__); - tty = port->tty; - if (!tty) { - dbg("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = mos7720_write(port, &stop_char, 1); + status = mos7720_write(tty, port, &stop_char, 1); if (status <= 0) return; } @@ -764,11 +762,11 @@ static void mos7720_throttle(struct usb_serial_port *port) } } -static void mos7720_unthrottle(struct usb_serial_port *port) +static void mos7720_unthrottle(struct tty_struct *tty) { - struct tty_struct *tty; - int status; + struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7720_port = usb_get_serial_port_data(port); + int status; if (mos7720_port == NULL) return; @@ -780,16 +778,10 @@ static void mos7720_unthrottle(struct usb_serial_port *port) dbg("%s: Entering ..........", __func__); - tty = port->tty; - if (!tty) { - dbg("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = mos7720_write(port, &start_char, 1); + status = mos7720_write(tty, port, &start_char, 1); if (status <= 0) return; } @@ -819,9 +811,9 @@ static int set_higher_rates(struct moschip_port *mos7720_port, port = mos7720_port->port; serial = port->serial; - /*********************************************** - * Init Sequence for higher rates - ***********************************************/ + /*********************************************** + * Init Sequence for higher rates + ***********************************************/ dbg("Sending Setting Commands .........."); port_number = port->number - port->serial->minor; @@ -832,7 +824,7 @@ static int set_higher_rates(struct moschip_port *mos7720_port, data = 0x0CF; send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data); data = 0x00b; - mos7720_port->shadowMCR = data; + mos7720_port->shadowMCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); data = 0x00b; send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); @@ -843,12 +835,12 @@ static int set_higher_rates(struct moschip_port *mos7720_port, send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); - /*********************************************** - * Set for higher rates * - ***********************************************/ + /*********************************************** + * Set for higher rates * + ***********************************************/ data = baud * 0x10; - send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data); + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); data = 0x003; send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); @@ -856,34 +848,33 @@ static int set_higher_rates(struct moschip_port *mos7720_port, send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); data = 0x02b; - mos7720_port->shadowMCR = data; + mos7720_port->shadowMCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); data = 0x02b; send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); - /*********************************************** - * Set DLL/DLM - ***********************************************/ + /*********************************************** + * Set DLL/DLM + ***********************************************/ data = mos7720_port->shadowLCR | UART_LCR_DLAB; - mos7720_port->shadowLCR = data; + mos7720_port->shadowLCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); data = 0x001; /* DLL */ - send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); + send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); data = 0x000; /* DLM */ - send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; - mos7720_port->shadowLCR = data; + mos7720_port->shadowLCR = data; send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); return 0; } /* baud rate information */ -struct divisor_table_entry -{ +struct divisor_table_entry { __u32 baudrate; __u16 divisor; }; @@ -932,8 +923,8 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor) } } - /* After trying for all the standard baud rates * - * Try calculating the divisor for this baud rate */ + /* After trying for all the standard baud rates * + * Try calculating the divisor for this baud rate */ if (baudrate > 75 && baudrate < 230400) { /* get the divisor */ custom = (__u16)(230400L / baudrate); @@ -945,7 +936,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor) custom++; *divisor = custom; - dbg("Baud %d = %d",baudrate, custom); + dbg("Baud %d = %d", baudrate, custom); return 0; } @@ -979,29 +970,29 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, number = port->number - port->serial->minor; dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate); - /* Calculate the Divisor */ + /* Calculate the Divisor */ status = calc_baud_rate_divisor(baudrate, &divisor); if (status) { err("%s - bad baud rate", __func__); return status; } - /* Enable access to divisor latch */ - data = mos7720_port->shadowLCR | UART_LCR_DLAB; - mos7720_port->shadowLCR = data; - send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data); + /* Enable access to divisor latch */ + data = mos7720_port->shadowLCR | UART_LCR_DLAB; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data); /* Write the divisor */ data = ((unsigned char)(divisor & 0xff)); - send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data); + send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data); data = ((unsigned char)((divisor & 0xff00) >> 8)); - send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data); + send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data); - /* Disable access to divisor latch */ - data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; - mos7720_port->shadowLCR = data; - send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data); + /* Disable access to divisor latch */ + data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data); return status; } @@ -1011,12 +1002,12 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, * This routine is called to set the UART on the device to match * the specified new settings. */ -static void change_port_settings(struct moschip_port *mos7720_port, +static void change_port_settings(struct tty_struct *tty, + struct moschip_port *mos7720_port, struct ktermios *old_termios) { struct usb_serial_port *port; struct usb_serial *serial; - struct tty_struct *tty; int baud; unsigned cflag; unsigned iflag; @@ -1042,8 +1033,6 @@ static void change_port_settings(struct moschip_port *mos7720_port, return; } - tty = mos7720_port->port->tty; - dbg("%s: Entering ..........", __func__); lData = UART_LCR_WLEN8; @@ -1106,29 +1095,31 @@ static void change_port_settings(struct moschip_port *mos7720_port, #define LCR_PAR_MASK 0x38 /* Mask for parity field */ /* Update the LCR with the correct value */ - mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); + mos7720_port->shadowLCR &= + ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); mos7720_port->shadowLCR |= (lData | lParity | lStop); /* Disable Interrupts */ data = 0x00; - send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data); + send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, + UART_IER, &data); data = 0x00; - send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); + send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); data = 0xcf; - send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); + send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); /* Send the updated LCR value to the mos7720 */ data = mos7720_port->shadowLCR; - send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data); + send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data); - data = 0x00b; - mos7720_port->shadowMCR = data; - send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); - data = 0x00b; - send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + data = 0x00b; + mos7720_port->shadowMCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + data = 0x00b; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); /* set up the MCR register and send it to the mos7720 */ mos7720_port->shadowMCR = UART_MCR_OUT2; @@ -1137,9 +1128,8 @@ static void change_port_settings(struct moschip_port *mos7720_port, if (cflag & CRTSCTS) { mos7720_port->shadowMCR |= (UART_MCR_XONANY); - - /* To set hardware flow control to the specified * - * serial port, in SP1/2_CONTROL_REG */ + /* To set hardware flow control to the specified * + * serial port, in SP1/2_CONTROL_REG */ if (port->number) { data = 0x001; send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, @@ -1198,14 +1188,13 @@ static void change_port_settings(struct moschip_port *mos7720_port, * this function is called by the tty driver when it wants to change the * termios structure. */ -static void mos7720_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) +static void mos7720_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { int status; unsigned int cflag; struct usb_serial *serial; struct moschip_port *mos7720_port; - struct tty_struct *tty; serial = port->serial; @@ -1214,15 +1203,12 @@ static void mos7720_set_termios(struct usb_serial_port *port, if (mos7720_port == NULL) return; - tty = port->tty; - - if (!mos7720_port->open) { dbg("%s - port not opened", __func__); return; } - dbg("%s\n","setting termios - ASPIRE"); + dbg("%s\n", "setting termios - ASPIRE"); cflag = tty->termios->c_cflag; @@ -1237,14 +1223,14 @@ static void mos7720_set_termios(struct usb_serial_port *port, dbg("%s - port %d", __func__, port->number); /* change the port settings to the new ones specified */ - change_port_settings(mos7720_port, old_termios); + change_port_settings(tty, mos7720_port, old_termios); - if(!port->read_urb) { - dbg("%s","URB KILLED !!!!!\n"); + if (!port->read_urb) { + dbg("%s", "URB KILLED !!!!!\n"); return; } - if(port->read_urb->status != -EINPROGRESS) { + if (port->read_urb->status != -EINPROGRESS) { port->read_urb->dev = serial->dev; status = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (status) @@ -1264,13 +1250,13 @@ static void mos7720_set_termios(struct usb_serial_port *port, * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int get_lsr_info(struct moschip_port *mos7720_port, - unsigned int __user *value) +static int get_lsr_info(struct tty_struct *tty, + struct moschip_port *mos7720_port, unsigned int __user *value) { int count; unsigned int result = 0; - count = mos7720_chars_in_buffer(mos7720_port->port); + count = mos7720_chars_in_buffer(tty); if (count == 0) { dbg("%s -- Empty", __func__); result = TIOCSER_TEMT; @@ -1290,7 +1276,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port, unsigned int __user *value) { unsigned int result = 0; - struct tty_struct *tty = mos7720_port->port->tty; + struct tty_struct *tty = mos7720_port->port->port.tty; if (!tty) return -ENOIOCTLCMD; @@ -1316,7 +1302,7 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, if (mos7720_port == NULL) return -1; - port = (struct usb_serial_port*)mos7720_port->port; + port = (struct usb_serial_port *)mos7720_port->port; mcr = mos7720_port->shadowMCR; if (copy_from_user(&arg, value, sizeof(int))) @@ -1397,7 +1383,7 @@ static int get_serial_info(struct moschip_port *mos7720_port, tmp.port = mos7720_port->port->number; tmp.irq = 0; tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; - tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; + tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; tmp.baud_base = 9600; tmp.close_delay = 5*HZ; tmp.closing_wait = 30*HZ; @@ -1407,9 +1393,10 @@ static int get_serial_info(struct moschip_port *mos7720_port, return 0; } -static int mos7720_ioctl(struct usb_serial_port *port, struct file *file, +static int mos7720_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7720_port; struct async_icount cnow; struct async_icount cprev; @@ -1431,14 +1418,16 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file, case TIOCSERGETLSR: dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); - return get_lsr_info(mos7720_port, (unsigned int __user *)arg); + return get_lsr_info(tty, mos7720_port, + (unsigned int __user *)arg); return 0; + /* FIXME: These should be using the mode methods */ case TIOCMBIS: case TIOCMBIC: case TIOCMSET: - dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__, - port->number); + dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", + __func__, port->number); return set_modem_info(mos7720_port, cmd, (unsigned int __user *)arg); @@ -1452,10 +1441,6 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file, return get_serial_info(mos7720_port, (struct serial_struct __user *)arg); - case TIOCSSERIAL: - dbg("%s (%d) TIOCSSERIAL", __func__, port->number); - break; - case TIOCMIWAIT: dbg("%s (%d) TIOCMIWAIT", __func__, port->number); cprev = mos7720_port->icount; @@ -1469,7 +1454,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file, if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { return 0; } cprev = cnow; @@ -1492,7 +1477,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file, icount.buf_overrun = cnow.buf_overrun; dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, - port->number, icount.rx, icount.tx ); + port->number, icount.rx, icount.tx); if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) return -EFAULT; return 0; @@ -1543,7 +1528,8 @@ static int mos7720_startup(struct usb_serial *serial) /* Initialize all port interrupt end point to port 0 int * endpoint. Our device has only one interrupt endpoint * comman to all ports */ - serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; + serial->port[i]->interrupt_in_endpointAddress = + serial->port[0]->interrupt_in_endpointAddress; mos7720_port->port = serial->port[i]; usb_set_serial_port_data(serial->port[i], mos7720_port); @@ -1555,13 +1541,15 @@ static int mos7720_startup(struct usb_serial *serial) /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ); + (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); - send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data); // LSR For Port 1 - dbg("LSR:%x",data); + /* LSR For Port 1 */ + send_mos_cmd(serial, MOS_READ, 0x00, UART_LSR, &data); + dbg("LSR:%x", data); - send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data); // LSR For Port 2 - dbg("LSR:%x",data); + /* LSR For Port 2 */ + send_mos_cmd(serial, MOS_READ, 0x01, UART_LSR, &data); + dbg("LSR:%x", data); return 0; } @@ -1571,7 +1559,7 @@ static void mos7720_shutdown(struct usb_serial *serial) int i; /* free private structure allocated for serial port */ - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) { kfree(usb_get_serial_port_data(serial->port[i])); usb_set_serial_port_data(serial->port[i], NULL); } @@ -1651,8 +1639,8 @@ module_init(moschip7720_init); module_exit(moschip7720_exit); /* Module information */ -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 78f2f6db494d..09d82062b973 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -33,7 +33,7 @@ #include <linux/serial.h> #include <linux/usb.h> #include <linux/usb/serial.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> /* * Version Information @@ -82,8 +82,8 @@ * Defines used for sending commands to port */ -#define WAIT_FOR_EVER (HZ * 0 ) /* timeout urb is wait for ever */ -#define MOS_WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ +#define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */ +#define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */ #define MOS_PORT1 0x0200 #define MOS_PORT2 0x0300 @@ -102,8 +102,8 @@ #define MAX_NAME_LEN 64 -#define ZLP_REG1 0x3A //Zero_Flag_Reg1 58 -#define ZLP_REG5 0x3E //Zero_Flag_Reg5 62 +#define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */ +#define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */ /* For higher baud Rates use TIOCEXBAUD */ #define TIOCEXBAUD 0x5462 @@ -142,7 +142,7 @@ #define MOS_MSR_DELTA_RI 0x40 #define MOS_MSR_DELTA_CD 0x80 -// Serial Port register Address +/* Serial Port register Address */ #define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01)) #define FIFO_CONTROL_REGISTER ((__u16)(0x02)) #define LINE_CONTROL_REGISTER ((__u16)(0x03)) @@ -201,11 +201,11 @@ struct moschip_port { struct async_icount icount; struct usb_serial_port *port; /* loop back to the owner of this object */ - /*Offsets */ + /* Offsets */ __u8 SpRegOffset; __u8 ControlRegOffset; __u8 DcrRegOffset; - //for processing control URBS in interrupt context + /* for processing control URBS in interrupt context */ struct urb *control_urb; struct usb_ctrlrequest *dr; char *ctrl_buf; @@ -244,7 +244,7 @@ static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg, */ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, - __u16 * val) + __u16 *val) { struct usb_device *dev = port->serial->dev; int ret = 0; @@ -269,16 +269,15 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, struct usb_device *dev = port->serial->dev; val = val & 0x00ff; - // For the UART control registers, the application number need to be Or'ed + /* For the UART control registers, the application number need + to be Or'ed */ if (port->serial->num_ports == 4) { - val |= - (((__u16) port->number - (__u16) (port->serial->minor)) + - 1) << 8; + val |= (((__u16) port->number - + (__u16) (port->serial->minor)) + 1) << 8; dbg("mos7840_set_uart_reg application number is %x\n", val); } else { if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { - val |= - (((__u16) port->number - + val |= (((__u16) port->number - (__u16) (port->serial->minor)) + 1) << 8; dbg("mos7840_set_uart_reg application number is %x\n", val); @@ -302,14 +301,15 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, * by passing usb_rcvctrlpipe function as parameter. */ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, - __u16 * val) + __u16 *val) { struct usb_device *dev = port->serial->dev; int ret = 0; __u16 Wval; - //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); - /*Wval is same as application number */ + /* dbg("application number is %4x \n", + (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */ + /* Wval is same as application number */ if (port->serial->num_ports == 4) { Wval = (((__u16) port->number - (__u16) (port->serial->minor)) + @@ -317,14 +317,12 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, dbg("mos7840_get_uart_reg application number is %x\n", Wval); } else { if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { - Wval = - (((__u16) port->number - + Wval = (((__u16) port->number - (__u16) (port->serial->minor)) + 1) << 8; dbg("mos7840_get_uart_reg application number is %x\n", Wval); } else { - Wval = - (((__u16) port->number - + Wval = (((__u16) port->number - (__u16) (port->serial->minor)) + 2) << 8; dbg("mos7840_get_uart_reg application number is %x\n", Wval); @@ -406,11 +404,11 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) dbg("%s - %02x", __func__, new_lsr); if (new_lsr & SERIAL_LSR_BI) { - // - // Parity and Framing errors only count if they - // occur exclusive of a break being - // received. - // + /* + * Parity and Framing errors only count if they + * occur exclusive of a break being + * received. + */ new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI); } @@ -492,7 +490,7 @@ exit: } static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, - __u16 * val) + __u16 *val) { struct usb_device *dev = mcs->port->serial->dev; struct usb_ctrlrequest *dr = mcs->dr; @@ -501,7 +499,7 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, dr->bRequestType = MCS_RD_RTYPE; dr->bRequest = MCS_RDREQ; - dr->wValue = cpu_to_le16(Wval); //0; + dr->wValue = cpu_to_le16(Wval); /* 0 */ dr->wIndex = cpu_to_le16(reg); dr->wLength = cpu_to_le16(2); @@ -607,7 +605,8 @@ static void mos7840_interrupt_callback(struct urb *urb) } } } - if (!(rv < 0)) /* the completion handler for the control urb will resubmit */ + if (!(rv < 0)) + /* the completion handler for the control urb will resubmit */ return; exit: result = usb_submit_urb(urb, GFP_ATOMIC); @@ -656,8 +655,8 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port, if (!port || mos7840_port_paranoia_check(port, function) || mos7840_serial_paranoia_check(port->serial, function)) { - /* then say that we don't have a valid usb_serial thing, which will - * end up genrating -ENODEV return values */ + /* then say that we don't have a valid usb_serial thing, + * which will end up genrating -ENODEV return values */ return NULL; } @@ -710,7 +709,7 @@ static void mos7840_bulk_in_callback(struct urb *urb) dbg("%s", "Entering ........... \n"); if (urb->actual_length) { - tty = mos7840_port->port->tty; + tty = mos7840_port->port->port.tty; if (tty) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); @@ -741,8 +740,8 @@ static void mos7840_bulk_in_callback(struct urb *urb) /***************************************************************************** * mos7840_bulk_out_data_callback - * this is the callback function for when we have finished sending serial data - * on the bulk out endpoint. + * this is the callback function for when we have finished sending + * serial data on the bulk out endpoint. *****************************************************************************/ static void mos7840_bulk_out_data_callback(struct urb *urb) @@ -774,7 +773,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) dbg("%s \n", "Entering ........."); - tty = mos7840_port->port->tty; + tty = mos7840_port->port->port.tty; if (tty && mos7840_port->open) tty_wakeup(tty); @@ -804,7 +803,8 @@ static int mos7840_serial_probe(struct usb_serial *serial, * Otherwise we return a negative error number. *****************************************************************************/ -static int mos7840_open(struct usb_serial_port *port, struct file *filp) +static int mos7840_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int response; int j; @@ -847,7 +847,8 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp) continue; } - urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, + GFP_KERNEL); if (!urb->transfer_buffer) { usb_free_urb(urb); mos7840_port->write_urb_pool[j] = NULL; @@ -868,9 +869,8 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp) * 0x08 : SP1/2 Control Reg *****************************************************************************/ -//NEED to check the following Block + /* NEED to check the following Block */ - status = 0; Data = 0x0; status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); if (status < 0) { @@ -890,36 +890,35 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp) dbg("writing Spreg failed\n"); return -1; } -//End of block to be checked + /* End of block to be checked */ - status = 0; Data = 0x0; - status = - mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); + status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, + &Data); if (status < 0) { dbg("Reading Controlreg failed\n"); return -1; } - Data |= 0x08; //Driver done bit - Data |= 0x20; //rx_disable - status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); + Data |= 0x08; /* Driver done bit */ + Data |= 0x20; /* rx_disable */ + status = mos7840_set_reg_sync(port, + mos7840_port->ControlRegOffset, Data); if (status < 0) { dbg("writing Controlreg failed\n"); return -1; } - //do register settings here - // Set all regs to the device default values. - //////////////////////////////////// - // First Disable all interrupts. - //////////////////////////////////// - + /* do register settings here */ + /* Set all regs to the device default values. */ + /*********************************** + * First Disable all interrupts. + ***********************************/ Data = 0x00; status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); if (status < 0) { dbg("disableing interrupts failed\n"); return -1; } - // Set FIFO_CONTROL_REGISTER to the default value + /* Set FIFO_CONTROL_REGISTER to the default value */ Data = 0x00; status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); if (status < 0) { @@ -946,90 +945,73 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp) status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); mos7840_port->shadowLCR = Data; - Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80 + Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); Data = 0x0c; - status = 0; status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); Data = 0x0; - status = 0; status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); Data = 0x00; - status = 0; status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); Data = Data & ~SERIAL_LCR_DLAB; - status = 0; status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); mos7840_port->shadowLCR = Data; - //clearing Bulkin and Bulkout Fifo + /* clearing Bulkin and Bulkout Fifo */ Data = 0x0; - status = 0; status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); Data = Data | 0x0c; - status = 0; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); Data = Data & ~0x0c; - status = 0; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); - //Finally enable all interrupts - Data = 0x0; + /* Finally enable all interrupts */ Data = 0x0c; - status = 0; status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); - //clearing rx_disable + /* clearing rx_disable */ Data = 0x0; - status = 0; - status = - mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); + status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, + &Data); Data = Data & ~0x20; - status = 0; - status = - mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); + status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, + Data); - // rx_negate + /* rx_negate */ Data = 0x0; - status = 0; - status = - mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); + status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, + &Data); Data = Data | 0x10; - status = 0; - status = - mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); + status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, + Data); /* force low_latency on so that our tty_push actually forces * * the data through,otherwise it is scheduled, and with * * high data rates (like with OHCI) data can get lost. */ + if (tty) + tty->low_latency = 1; - if (port->tty) - port->tty->low_latency = 1; -/* Check to see if we've set up our endpoint info yet * - * (can't set it up in mos7840_startup as the structures * - * were not set up at that time.) */ + /* Check to see if we've set up our endpoint info yet * + * (can't set it up in mos7840_startup as the structures * + * were not set up at that time.) */ if (port0->open_ports == 1) { if (serial->port[0]->interrupt_in_buffer == NULL) { - /* set up interrupt urb */ - usb_fill_int_urb(serial->port[0]->interrupt_in_urb, - serial->dev, - usb_rcvintpipe(serial->dev, - serial->port[0]-> - interrupt_in_endpointAddress), - serial->port[0]->interrupt_in_buffer, - serial->port[0]->interrupt_in_urb-> - transfer_buffer_length, - mos7840_interrupt_callback, - serial, - serial->port[0]->interrupt_in_urb-> - interval); + serial->dev, + usb_rcvintpipe(serial->dev, + serial->port[0]->interrupt_in_endpointAddress), + serial->port[0]->interrupt_in_buffer, + serial->port[0]->interrupt_in_urb-> + transfer_buffer_length, + mos7840_interrupt_callback, + serial, + serial->port[0]->interrupt_in_urb->interval); /* start interrupt read for mos7840 * * will continue as long as mos7840 is connected */ @@ -1084,14 +1066,16 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp) memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); /* initialize our port settings */ - mos7840_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */ + /* Must set to enable ints! */ + mos7840_port->shadowMCR = MCR_MASTER_IE; /* send a open port command */ mos7840_port->open = 1; - //mos7840_change_port_settings(mos7840_port,old_termios); + /* mos7840_change_port_settings(mos7840_port,old_termios); */ mos7840_port->icount.tx = 0; mos7840_port->icount.rx = 0; - dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n", serial, mos7840_port, port); + dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n", + serial, mos7840_port, port); return 0; @@ -1104,11 +1088,12 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp) * been written, but hasn't made it out the port yet) * If successful, we return the number of bytes left to be written in the * system, - * Otherwise we return a negative error number. + * Otherwise we return zero. *****************************************************************************/ -static int mos7840_chars_in_buffer(struct usb_serial_port *port) +static int mos7840_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int i; int chars = 0; unsigned long flags; @@ -1118,22 +1103,20 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port) if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Invalid port \n"); - return -1; + return 0; } mos7840_port = mos7840_get_port_private(port); if (mos7840_port == NULL) { dbg("%s \n", "mos7840_break:leaving ..........."); - return -1; + return 0; } - spin_lock_irqsave(&mos7840_port->pool_lock,flags); - for (i = 0; i < NUM_URBS; ++i) { - if (mos7840_port->busy[i]) { + spin_lock_irqsave(&mos7840_port->pool_lock, flags); + for (i = 0; i < NUM_URBS; ++i) + if (mos7840_port->busy[i]) chars += URB_TRANSFER_BUFFER_SIZE; - } - } - spin_unlock_irqrestore(&mos7840_port->pool_lock,flags); + spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); dbg("%s - returns %d", __func__, chars); return chars; @@ -1149,7 +1132,8 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port) * 3. A timeout of 3 seconds without activity has expired * ************************************************************************/ -static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port) +static void mos7840_block_until_tx_empty(struct tty_struct *tty, + struct moschip_port *mos7840_port) { int timeout = HZ / 10; int wait = 30; @@ -1157,12 +1141,11 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port) while (1) { - count = mos7840_chars_in_buffer(mos7840_port->port); + count = mos7840_chars_in_buffer(tty); /* Check for Buffer status */ - if (count <= 0) { + if (count <= 0) return; - } /* Block the thread for a while */ interruptible_sleep_on_timeout(&mos7840_port->wait_chase, @@ -1185,7 +1168,8 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port) * this function is called by the tty driver when a port is closed *****************************************************************************/ -static void mos7840_close(struct usb_serial_port *port, struct file *filp) +static void mos7840_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial; struct moschip_port *mos7840_port; @@ -1226,32 +1210,28 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp) } } - if (serial->dev) { + if (serial->dev) /* flush and block until tx is empty */ - mos7840_block_until_tx_empty(mos7840_port); - } + mos7840_block_until_tx_empty(tty, mos7840_port); /* While closing port, shutdown all bulk read, write * * and interrupt read if they exists */ if (serial->dev) { - if (mos7840_port->write_urb) { dbg("%s", "Shutdown bulk write\n"); usb_kill_urb(mos7840_port->write_urb); } - if (mos7840_port->read_urb) { dbg("%s", "Shutdown bulk read\n"); usb_kill_urb(mos7840_port->read_urb); } if ((&mos7840_port->control_urb)) { dbg("%s", "Shutdown control read\n"); - // usb_kill_urb (mos7840_port->control_urb); - + /*/ usb_kill_urb (mos7840_port->control_urb); */ } } -// if(mos7840_port->ctrl_buf != NULL) -// kfree(mos7840_port->ctrl_buf); +/* if(mos7840_port->ctrl_buf != NULL) */ +/* kfree(mos7840_port->ctrl_buf); */ port0->open_ports--; dbg("mos7840_num_open_ports in close%d:in port%d\n", port0->open_ports, port->number); @@ -1264,10 +1244,8 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp) if (mos7840_port->write_urb) { /* if this urb had a transfer buffer already (old tx) free it */ - - if (mos7840_port->write_urb->transfer_buffer != NULL) { + if (mos7840_port->write_urb->transfer_buffer != NULL) kfree(mos7840_port->write_urb->transfer_buffer); - } usb_free_urb(mos7840_port->write_urb); } @@ -1293,20 +1271,19 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp) * ************************************************************************/ -static void mos7840_block_until_chase_response(struct moschip_port - *mos7840_port) +static void mos7840_block_until_chase_response(struct tty_struct *tty, + struct moschip_port *mos7840_port) { int timeout = 1 * HZ; int wait = 10; int count; while (1) { - count = mos7840_chars_in_buffer(mos7840_port->port); + count = mos7840_chars_in_buffer(tty); /* Check for Buffer status */ - if (count <= 0) { + if (count <= 0) return; - } /* Block the thread for a while */ interruptible_sleep_on_timeout(&mos7840_port->wait_chase, @@ -1328,8 +1305,9 @@ static void mos7840_block_until_chase_response(struct moschip_port * mos7840_break * this function sends a break to the port *****************************************************************************/ -static void mos7840_break(struct usb_serial_port *port, int break_state) +static void mos7840_break(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; unsigned char data; struct usb_serial *serial; struct moschip_port *mos7840_port; @@ -1350,21 +1328,17 @@ static void mos7840_break(struct usb_serial_port *port, int break_state) mos7840_port = mos7840_get_port_private(port); - if (mos7840_port == NULL) { + if (mos7840_port == NULL) return; - } - - if (serial->dev) { + if (serial->dev) /* flush and block until tx is empty */ - mos7840_block_until_chase_response(mos7840_port); - } + mos7840_block_until_chase_response(tty, mos7840_port); - if (break_state == -1) { + if (break_state == -1) data = mos7840_port->shadowLCR | LCR_SET_BREAK; - } else { + else data = mos7840_port->shadowLCR & ~LCR_SET_BREAK; - } mos7840_port->shadowLCR = data; dbg("mcs7840_break mos7840_port->shadowLCR is %x\n", @@ -1383,8 +1357,9 @@ static void mos7840_break(struct usb_serial_port *port, int break_state) * Otherwise we return a negative error number. *****************************************************************************/ -static int mos7840_write_room(struct usb_serial_port *port) +static int mos7840_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int i; int room = 0; unsigned long flags; @@ -1406,9 +1381,8 @@ static int mos7840_write_room(struct usb_serial_port *port) spin_lock_irqsave(&mos7840_port->pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { - if (!mos7840_port->busy[i]) { + if (!mos7840_port->busy[i]) room += URB_TRANSFER_BUFFER_SIZE; - } } spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); @@ -1426,7 +1400,7 @@ static int mos7840_write_room(struct usb_serial_port *port) * return a negative error number. *****************************************************************************/ -static int mos7840_write(struct usb_serial_port *port, +static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *data, int count) { int status; @@ -1438,45 +1412,41 @@ static int mos7840_write(struct usb_serial_port *port, struct moschip_port *mos7840_port; struct usb_serial *serial; struct urb *urb; - //__u16 Data; + /* __u16 Data; */ const unsigned char *current_position = data; unsigned char *data1; dbg("%s \n", "entering ..........."); - //dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR); + /* dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", + mos7840_port->shadowLCR); */ #ifdef NOTMOS7840 Data = 0x00; - status = 0; status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); mos7840_port->shadowLCR = Data; dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data); dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", mos7840_port->shadowLCR); - //Data = 0x03; - //status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); - //mos7840_port->shadowLCR=Data;//Need to add later + /* Data = 0x03; */ + /* status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); */ + /* mos7840_port->shadowLCR=Data;//Need to add later */ - Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80 - status = 0; + Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); - //Data = 0x0c; - //status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); + /* Data = 0x0c; */ + /* status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); */ Data = 0x00; - status = 0; status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data); dbg("mos7840_write:DLL value is %x\n", Data); Data = 0x0; - status = 0; status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data); dbg("mos7840_write:DLM value is %x\n", Data); Data = Data & ~SERIAL_LCR_DLAB; dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", mos7840_port->shadowLCR); - status = 0; status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); #endif @@ -1555,8 +1525,7 @@ static int mos7840_write(struct usb_serial_port *port, mos7840_port->icount.tx += transfer_size; smp_wmb(); dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); - exit: - +exit: return bytes_sent; } @@ -1567,10 +1536,10 @@ static int mos7840_write(struct usb_serial_port *port, * being read from the port. *****************************************************************************/ -static void mos7840_throttle(struct usb_serial_port *port) +static void mos7840_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port; - struct tty_struct *tty; int status; if (mos7840_port_paranoia_check(port, __func__)) { @@ -1592,32 +1561,20 @@ static void mos7840_throttle(struct usb_serial_port *port) dbg("%s", "Entering .......... \n"); - tty = port->tty; - if (!tty) { - dbg("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = mos7840_write(port, &stop_char, 1); - if (status <= 0) { + status = mos7840_write(tty, port, &stop_char, 1); + if (status <= 0) return; - } } - /* if we are implementing RTS/CTS, toggle that line */ if (tty->termios->c_cflag & CRTSCTS) { mos7840_port->shadowMCR &= ~MCR_RTS; - status = 0; - status = - mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, + status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); - - if (status < 0) { + if (status < 0) return; - } } return; @@ -1625,12 +1582,13 @@ static void mos7840_throttle(struct usb_serial_port *port) /***************************************************************************** * mos7840_unthrottle - * this function is called by the tty driver when it wants to resume the data - * being read from the port (called after SerialThrottle is called) + * this function is called by the tty driver when it wants to resume + * the data being read from the port (called after mos7840_throttle is + * called) *****************************************************************************/ -static void mos7840_unthrottle(struct usb_serial_port *port) +static void mos7840_unthrottle(struct tty_struct *tty) { - struct tty_struct *tty; + struct usb_serial_port *port = tty->driver_data; int status; struct moschip_port *mos7840_port = mos7840_get_port_private(port); @@ -1649,43 +1607,32 @@ static void mos7840_unthrottle(struct usb_serial_port *port) dbg("%s", "Entering .......... \n"); - tty = port->tty; - if (!tty) { - dbg("%s - no tty available", __func__); - return; - } - /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = mos7840_write(port, &start_char, 1); - if (status <= 0) { + status = mos7840_write(tty, port, &start_char, 1); + if (status <= 0) return; - } } /* if we are implementing RTS/CTS, toggle that line */ if (tty->termios->c_cflag & CRTSCTS) { mos7840_port->shadowMCR |= MCR_RTS; - status = 0; - status = - mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, + status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); - if (status < 0) { + if (status < 0) return; - } } - - return; } -static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file) +static int mos7840_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port; unsigned int result; __u16 msr; __u16 mcr; - int status = 0; + int status; mos7840_port = mos7840_get_port_private(port); dbg("%s - port %d", __func__, port->number); @@ -1708,9 +1655,10 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file) return result; } -static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file, +static int mos7840_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port; unsigned int mcr; int status; @@ -1755,7 +1703,7 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file, * baud rate. *****************************************************************************/ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, - __u16 * clk_sel_val) + __u16 *clk_sel_val) { dbg("%s - %d", __func__, baudRate); @@ -1807,9 +1755,8 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, /* Check for round off */ round1 = (__u16) (2304000L / baudrate); round = (__u16) (round1 - (custom * 10)); - if (round > 4) { + if (round > 4) custom++; - } *divisor = custom; dbg(" Baud %d = %d\n", baudrate, custom); @@ -1857,16 +1804,15 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, dbg("%s - port = %d, baud = %d", __func__, mos7840_port->port->number, baudRate); - //reset clk_uart_sel in spregOffset + /* reset clk_uart_sel in spregOffset */ if (baudRate > 115200) { #ifdef HW_flow_control - //NOTE: need to see the pther register to modify - //setting h/w flow control bit to 1; - status = 0; + /* NOTE: need to see the pther register to modify */ + /* setting h/w flow control bit to 1 */ Data = 0x2b; mos7840_port->shadowMCR = Data; - status = - mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, + Data); if (status < 0) { dbg("Writing spreg failed in set_serial_baud\n"); return -1; @@ -1875,12 +1821,11 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, } else { #ifdef HW_flow_control - //setting h/w flow control bit to 0; - status = 0; + / *setting h/w flow control bit to 0 */ Data = 0xb; mos7840_port->shadowMCR = Data; - status = - mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, + Data); if (status < 0) { dbg("Writing spreg failed in set_serial_baud\n"); return -1; @@ -1889,25 +1834,20 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, } - if (1) //baudRate <= 115200) - { + if (1) { /* baudRate <= 115200) */ clk_sel_val = 0x0; Data = 0x0; - status = 0; - status = - mos7840_calc_baud_rate_divisor(baudRate, &divisor, + status = mos7840_calc_baud_rate_divisor(baudRate, &divisor, &clk_sel_val); - status = - mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, - &Data); + status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, + &Data); if (status < 0) { dbg("reading spreg failed in set_serial_baud\n"); return -1; } Data = (Data & 0x8f) | clk_sel_val; - status = 0; - status = - mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); + status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, + Data); if (status < 0) { dbg("Writing spreg failed in set_serial_baud\n"); return -1; @@ -1939,7 +1879,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); } - return status; } @@ -1949,10 +1888,9 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, * the specified new settings. *****************************************************************************/ -static void mos7840_change_port_settings(struct moschip_port *mos7840_port, - struct ktermios *old_termios) +static void mos7840_change_port_settings(struct tty_struct *tty, + struct moschip_port *mos7840_port, struct ktermios *old_termios) { - struct tty_struct *tty; int baud; unsigned cflag; unsigned iflag; @@ -1988,8 +1926,6 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, return; } - tty = mos7840_port->port->tty; - dbg("%s", "Entering .......... \n"); lData = LCR_BITS_8; @@ -2033,9 +1969,8 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, dbg("%s - parity = none", __func__); } - if (cflag & CMSPAR) { + if (cflag & CMSPAR) lParity = lParity | 0x20; - } /* Change the Stop bit */ if (cflag & CSTOPB) { @@ -2077,16 +2012,13 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, /* set up the MCR register and send it to the mos7840 */ mos7840_port->shadowMCR = MCR_MASTER_IE; - if (cflag & CBAUD) { + if (cflag & CBAUD) mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS); - } - if (cflag & CRTSCTS) { + if (cflag & CRTSCTS) mos7840_port->shadowMCR |= (MCR_XON_ANY); - - } else { + else mos7840_port->shadowMCR &= ~(MCR_XON_ANY); - } Data = mos7840_port->shadowMCR; mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); @@ -2131,14 +2063,14 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, * the termios structure *****************************************************************************/ -static void mos7840_set_termios(struct usb_serial_port *port, +static void mos7840_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { int status; unsigned int cflag; struct usb_serial *serial; struct moschip_port *mos7840_port; - struct tty_struct *tty; dbg("mos7840_set_termios: START\n"); if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Invalid port \n"); @@ -2157,8 +2089,6 @@ static void mos7840_set_termios(struct usb_serial_port *port, if (mos7840_port == NULL) return; - tty = port->tty; - if (!mos7840_port->open) { dbg("%s - port not opened", __func__); return; @@ -2176,7 +2106,7 @@ static void mos7840_set_termios(struct usb_serial_port *port, /* change the port settings to the new ones specified */ - mos7840_change_port_settings(mos7840_port, old_termios); + mos7840_change_port_settings(tty, mos7840_port, old_termios); if (!mos7840_port->read_urb) { dbg("%s", "URB KILLED !!!!!\n"); @@ -2205,13 +2135,13 @@ static void mos7840_set_termios(struct usb_serial_port *port, * allows an RS485 driver to be written in user space. *****************************************************************************/ -static int mos7840_get_lsr_info(struct moschip_port *mos7840_port, +static int mos7840_get_lsr_info(struct tty_struct *tty, unsigned int __user *value) { int count; unsigned int result = 0; - count = mos7840_chars_in_buffer(mos7840_port->port); + count = mos7840_chars_in_buffer(tty); if (count == 0) { dbg("%s -- Empty", __func__); result = TIOCSER_TEMT; @@ -2227,6 +2157,8 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port, * function to set modem info *****************************************************************************/ +/* FIXME: Should be using the model control hooks */ + static int mos7840_set_modem_info(struct moschip_port *mos7840_port, unsigned int cmd, unsigned int __user *value) { @@ -2282,7 +2214,6 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port, mos7840_port->shadowMCR = mcr; Data = mos7840_port->shadowMCR; - status = 0; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); if (status < 0) { dbg("setting MODEM_CONTROL_REGISTER Failed\n"); @@ -2303,10 +2234,8 @@ static int mos7840_get_modem_info(struct moschip_port *mos7840_port, unsigned int result = 0; __u16 msr; unsigned int mcr = mos7840_port->shadowMCR; - int status = 0; - status = - mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER, - &msr); + mos7840_get_uart_reg(mos7840_port->port, + MODEM_STATUS_REGISTER, &msr); result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ @@ -2359,12 +2288,12 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port, * this function handles any ioctl calls to the driver *****************************************************************************/ -static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, +static int mos7840_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; void __user *argp = (void __user *)arg; struct moschip_port *mos7840_port; - struct tty_struct *tty; struct async_icount cnow; struct async_icount cprev; @@ -2381,8 +2310,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, if (mos7840_port == NULL) return -1; - tty = mos7840_port->port->tty; - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); switch (cmd) { @@ -2390,9 +2317,10 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, case TIOCSERGETLSR: dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); - return mos7840_get_lsr_info(mos7840_port, argp); + return mos7840_get_lsr_info(tty, argp); return 0; + /* FIXME: use the modem hooks and remove this */ case TIOCMBIS: case TIOCMBIC: case TIOCMSET: @@ -2418,7 +2346,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, dbg("%s (%d) TIOCMIWAIT", __func__, port->number); cprev = mos7840_port->icount; while (1) { - //interruptible_sleep_on(&mos7840_port->delta_msr_wait); + /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ mos7840_port->delta_msr_cond = 0; wait_event_interruptible(mos7840_port->delta_msr_wait, (mos7840_port-> @@ -2463,13 +2391,9 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, if (copy_to_user(argp, &icount, sizeof(icount))) return -EFAULT; return 0; - - case TIOCEXBAUD: - return 0; default: break; } - return -ENOIOCTLCMD; } @@ -2527,8 +2451,9 @@ static int mos7840_startup(struct usb_serial *serial) goto error; } - /* Initialize all port interrupt end point to port 0 int endpoint * - * Our device has only one interrupt end point comman to all port */ + /* Initialize all port interrupt end point to port 0 int + * endpoint. Our device has only one interrupt end point + * common to all port */ mos7840_port->port = serial->port[i]; mos7840_set_port_private(serial->port[i], mos7840_port); @@ -2564,27 +2489,23 @@ static int mos7840_startup(struct usb_serial *serial) mos7840_port->DcrRegOffset = 0x1c; } mos7840_dump_serial_port(mos7840_port); - mos7840_set_port_private(serial->port[i], mos7840_port); - //enable rx_disable bit in control register - - status = - mos7840_get_reg_sync(serial->port[i], - mos7840_port->ControlRegOffset, &Data); + /* enable rx_disable bit in control register */ + status = mos7840_get_reg_sync(serial->port[i], + mos7840_port->ControlRegOffset, &Data); if (status < 0) { dbg("Reading ControlReg failed status-0x%x\n", status); break; } else dbg("ControlReg Reading success val is %x, status%d\n", Data, status); - Data |= 0x08; //setting driver done bit - Data |= 0x04; //sp1_bit to have cts change reflect in modem status reg + Data |= 0x08; /* setting driver done bit */ + Data |= 0x04; /* sp1_bit to have cts change reflect in + modem status reg */ - //Data |= 0x20; //rx_disable bit - status = 0; - status = - mos7840_set_reg_sync(serial->port[i], + /* Data |= 0x20; //rx_disable bit */ + status = mos7840_set_reg_sync(serial->port[i], mos7840_port->ControlRegOffset, Data); if (status < 0) { dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status); @@ -2593,13 +2514,11 @@ static int mos7840_startup(struct usb_serial *serial) dbg("ControlReg Writing success(rx_disable) status%d\n", status); - //Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3 + /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 + and 0x24 in DCR3 */ Data = 0x01; - status = 0; - status = - mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + - 0), Data); + status = mos7840_set_reg_sync(serial->port[i], + (__u16) (mos7840_port->DcrRegOffset + 0), Data); if (status < 0) { dbg("Writing DCR0 failed status-0x%x\n", status); break; @@ -2607,11 +2526,8 @@ static int mos7840_startup(struct usb_serial *serial) dbg("DCR0 Writing success status%d\n", status); Data = 0x05; - status = 0; - status = - mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + - 1), Data); + status = mos7840_set_reg_sync(serial->port[i], + (__u16) (mos7840_port->DcrRegOffset + 1), Data); if (status < 0) { dbg("Writing DCR1 failed status-0x%x\n", status); break; @@ -2619,22 +2535,17 @@ static int mos7840_startup(struct usb_serial *serial) dbg("DCR1 Writing success status%d\n", status); Data = 0x24; - status = 0; - status = - mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + - 2), Data); + status = mos7840_set_reg_sync(serial->port[i], + (__u16) (mos7840_port->DcrRegOffset + 2), Data); if (status < 0) { dbg("Writing DCR2 failed status-0x%x\n", status); break; } else dbg("DCR2 Writing success status%d\n", status); - // write values in clkstart0x0 and clkmulti 0x20 + /* write values in clkstart0x0 and clkmulti 0x20 */ Data = 0x0; - status = 0; - status = - mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(serial->port[i], CLK_START_VALUE_REGISTER, Data); if (status < 0) { dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); @@ -2643,9 +2554,8 @@ static int mos7840_startup(struct usb_serial *serial) dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status); Data = 0x20; - status = - mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER, - Data); + status = mos7840_set_reg_sync(serial->port[i], + CLK_MULTI_REGISTER, Data); if (status < 0) { dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); @@ -2654,11 +2564,10 @@ static int mos7840_startup(struct usb_serial *serial) dbg("CLK_MULTI_REGISTER Writing success status%d\n", status); - //write value 0x0 to scratchpad register + /* write value 0x0 to scratchpad register */ Data = 0x00; - status = - mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER, - Data); + status = mos7840_set_uart_reg(serial->port[i], + SCRATCH_PAD_REGISTER, Data); if (status < 0) { dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); @@ -2667,21 +2576,17 @@ static int mos7840_startup(struct usb_serial *serial) dbg("SCRATCH_PAD_REGISTER Writing success status%d\n", status); - //Zero Length flag register + /* Zero Length flag register */ if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { Data = 0xff; - status = 0; status = mos7840_set_reg_sync(serial->port[i], - (__u16) (ZLP_REG1 + - ((__u16) - mos7840_port-> - port_num)), - Data); + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num)), Data); dbg("ZLIP offset%x\n", (__u16) (ZLP_REG1 + - ((__u16) mos7840_port->port_num))); + ((__u16) mos7840_port->port_num))); if (status < 0) { dbg("Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); @@ -2691,13 +2596,9 @@ static int mos7840_startup(struct usb_serial *serial) i + 2, status); } else { Data = 0xff; - status = 0; status = mos7840_set_reg_sync(serial->port[i], - (__u16) (ZLP_REG1 + - ((__u16) - mos7840_port-> - port_num) - - 0x1), Data); + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num) - 0x1), Data); dbg("ZLIP offset%x\n", (__u16) (ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); @@ -2712,14 +2613,16 @@ static int mos7840_startup(struct usb_serial *serial) } mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); - mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || !mos7840_port->dr) { + mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), + GFP_KERNEL); + if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || + !mos7840_port->dr) { status = -ENOMEM; goto error; } } - //Zero Length flag enable + /* Zero Length flag enable */ Data = 0x0f; status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); if (status < 0) { @@ -2762,7 +2665,7 @@ static void mos7840_shutdown(struct usb_serial *serial) return; } - /* check for the ports to be closed,close the ports and disconnect */ + /* check for the ports to be closed,close the ports and disconnect */ /* free private structure allocated for serial port * * stop reads and writes on all ports */ @@ -2843,20 +2746,12 @@ static int __init moschip7840_init(void) /* Register with the usb */ retval = usb_register(&io_driver); - - if (retval) - goto failed_usb_register; - if (retval == 0) { dbg("%s\n", "Leaving..."); return 0; } - - failed_usb_register: usb_serial_deregister(&moschip7840_4port_device); - - failed_port_device_register: - +failed_port_device_register: return retval; } diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 43c8894353bf..d6736531a0fa 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -64,7 +64,7 @@ static void navman_read_int_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); @@ -79,7 +79,8 @@ exit: __func__, result); } -static int navman_open(struct usb_serial_port *port, struct file *filp) +static int navman_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int result = 0; @@ -96,14 +97,15 @@ static int navman_open(struct usb_serial_port *port, struct file *filp) return result; } -static void navman_close(struct usb_serial_port *port, struct file *filp) +static void navman_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __func__, port->number); usb_kill_urb(port->interrupt_in_urb); } -static int navman_write(struct usb_serial_port *port, +static int navman_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { dbg("%s - port %d", __func__, port->number); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 7b7422f49478..ae8e227f3db2 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -5,26 +5,28 @@ * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * Please report both successes and troubles to the author at omninet@kroah.com - * + * * (05/30/2001) gkh - * switched from using spinlock to a semaphore, which fixes lots of problems. + * switched from using spinlock to a semaphore, which fixes lots of + * problems. * * (04/08/2001) gb * Identify version on module load. * * (11/01/2000) Adam J. Richter * usb_device_id table support - * + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. - * + * * (08/28/2000) gkh * Added locks for SMP safeness. - * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more + * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more * than once. * Fixed potential race in omninet_write_bulk_callback * @@ -43,7 +45,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -58,25 +60,29 @@ static int debug; #define ZYXEL_VENDOR_ID 0x0586 #define ZYXEL_OMNINET_ID 0x1000 -#define BT_IGNITIONPRO_ID 0x2000 /* This one seems to be a re-branded ZyXEL device */ +/* This one seems to be a re-branded ZyXEL device */ +#define BT_IGNITIONPRO_ID 0x2000 /* function prototypes */ -static int omninet_open (struct usb_serial_port *port, struct file *filp); -static void omninet_close (struct usb_serial_port *port, struct file *filp); -static void omninet_read_bulk_callback (struct urb *urb); -static void omninet_write_bulk_callback (struct urb *urb); -static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static int omninet_write_room (struct usb_serial_port *port); -static void omninet_shutdown (struct usb_serial *serial); -static int omninet_attach (struct usb_serial *serial); - -static struct usb_device_id id_table [] = { +static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static void omninet_read_bulk_callback(struct urb *urb); +static void omninet_write_bulk_callback(struct urb *urb); +static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static int omninet_write_room(struct tty_struct *tty); +static void omninet_shutdown(struct usb_serial *serial); +static int omninet_attach(struct usb_serial *serial); + +static struct usb_device_id id_table[] = { { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, { USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver omninet_driver = { .name = "omninet", @@ -130,34 +136,34 @@ static struct usb_serial_driver zyxel_omninet_device = { * */ -struct omninet_header -{ +struct omninet_header { __u8 oh_seq; __u8 oh_len; __u8 oh_xxx; __u8 oh_pad; }; -struct omninet_data -{ - __u8 od_outseq; // Sequence number for bulk_out URBs +struct omninet_data { + __u8 od_outseq; /* Sequence number for bulk_out URBs */ }; -static int omninet_attach (struct usb_serial *serial) +static int omninet_attach(struct usb_serial *serial) { struct omninet_data *od; struct usb_serial_port *port = serial->port[0]; - od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL ); - if( !od ) { - err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct omninet_data)); + od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); + if (!od) { + err("%s- kmalloc(%Zd) failed.", + __func__, sizeof(struct omninet_data)); return -ENOMEM; } usb_set_serial_port_data(port, od); return 0; } -static int omninet_open (struct usb_serial_port *port, struct file *filp) +static int omninet_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; struct usb_serial_port *wport; @@ -166,22 +172,24 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp) dbg("%s - port %d", __func__, port->number); wport = serial->port[1]; - wport->tty = port->tty; + wport->port.tty = tty; /* FIXME */ /* Start reading from the device */ - usb_fill_bulk_urb(port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, - omninet_read_bulk_callback, port); + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + omninet_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) { - err("%s - failed submitting read urb, error %d", __func__, result); - } - + if (result) + err("%s - failed submitting read urb, error %d", + __func__, result); return result; } -static void omninet_close (struct usb_serial_port *port, struct file * filp) +static void omninet_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __func__, port->number); usb_kill_urb(port->read_urb); @@ -192,14 +200,14 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp) #define OMNINET_HEADERLEN sizeof(struct omninet_header) #define OMNINET_BULKOUTSIZE (64 - OMNINET_HEADERLEN) -static void omninet_read_bulk_callback (struct urb *urb) +static void omninet_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; struct omninet_header *header = (struct omninet_header *) &data[0]; int status = urb->status; - int i; int result; + int i; dbg("%s - port %d", __func__, port->number); @@ -209,42 +217,46 @@ static void omninet_read_bulk_callback (struct urb *urb) return; } - if ((debug) && (header->oh_xxx != 0x30)) { + if (debug && header->oh_xxx != 0x30) { if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len); - for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) { - printk ("%.2x ", data[i]); - } - printk ("\n"); + printk(KERN_DEBUG __FILE__ + ": omninet_read %d: ", header->oh_len); + for (i = 0; i < (header->oh_len + + OMNINET_HEADERLEN); i++) + printk("%.2x ", data[i]); + printk("\n"); } } if (urb->actual_length && header->oh_len) { - for (i = 0; i < header->oh_len; i++) { - tty_insert_flip_char(port->tty, data[OMNINET_DATAOFFSET + i], 0); - } - tty_flip_buffer_push(port->tty); + tty_insert_flip_string(port->port.tty, + data + OMNINET_DATAOFFSET, header->oh_len); + tty_flip_buffer_push(port->port.tty); } /* Continue trying to always read */ - usb_fill_bulk_urb(urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), - urb->transfer_buffer, urb->transfer_buffer_length, - omninet_read_bulk_callback, port); + usb_fill_bulk_urb(urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + urb->transfer_buffer, urb->transfer_buffer_length, + omninet_read_bulk_callback, port); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", __func__, result); + err("%s - failed resubmitting read urb, error %d", + __func__, result); return; } -static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count) +static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { - struct usb_serial *serial = port->serial; - struct usb_serial_port *wport = serial->port[1]; + struct usb_serial *serial = port->serial; + struct usb_serial_port *wport = serial->port[1]; - struct omninet_data *od = usb_get_serial_port_data(port); - struct omninet_header *header = (struct omninet_header *) wport->write_urb->transfer_buffer; + struct omninet_data *od = usb_get_serial_port_data(port); + struct omninet_header *header = (struct omninet_header *) + wport->write_urb->transfer_buffer; int result; @@ -252,7 +264,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf if (count == 0) { dbg("%s - write request of 0 bytes", __func__); - return (0); + return 0; } spin_lock_bh(&wport->lock); @@ -266,9 +278,11 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; - memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); + memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, + buf, count); - usb_serial_debug_data(debug, &port->dev, __func__, count, wport->write_urb->transfer_buffer); + usb_serial_debug_data(debug, &port->dev, __func__, count, + wport->write_urb->transfer_buffer); header->oh_seq = od->od_outseq++; header->oh_len = count; @@ -282,7 +296,8 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); if (result) { wport->write_urb_busy = 0; - err("%s - failed submitting write urb, error %d", __func__, result); + err("%s - failed submitting write urb, error %d", + __func__, result); } else result = count; @@ -290,8 +305,9 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf } -static int omninet_write_room (struct usb_serial_port *port) +static int omninet_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; struct usb_serial_port *wport = serial->port[1]; @@ -303,12 +319,13 @@ static int omninet_write_room (struct usb_serial_port *port) dbg("%s - returns %d", __func__, room); - return (room); + return room; } -static void omninet_write_bulk_callback (struct urb *urb) +static void omninet_write_bulk_callback(struct urb *urb) { -/* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */ +/* struct omninet_header *header = (struct omninet_header *) + urb->transfer_buffer; */ struct usb_serial_port *port = urb->context; int status = urb->status; @@ -325,18 +342,18 @@ static void omninet_write_bulk_callback (struct urb *urb) } -static void omninet_shutdown (struct usb_serial *serial) +static void omninet_shutdown(struct usb_serial *serial) { struct usb_serial_port *wport = serial->port[1]; struct usb_serial_port *port = serial->port[0]; - dbg ("%s", __func__); + dbg("%s", __func__); usb_kill_urb(wport->write_urb); kfree(usb_get_serial_port_data(port)); } -static int __init omninet_init (void) +static int __init omninet_init(void) { int retval; retval = usb_serial_register(&zyxel_omninet_device); @@ -354,18 +371,18 @@ failed_usb_serial_register: } -static void __exit omninet_exit (void) +static void __exit omninet_exit(void) { - usb_deregister (&omninet_driver); - usb_serial_deregister (&zyxel_omninet_device); + usb_deregister(&omninet_driver); + usb_serial_deregister(&zyxel_omninet_device); } module_init(omninet_init); module_exit(omninet_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a73420dd052a..e4eca95f2b0f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -43,29 +43,25 @@ #include <linux/usb/serial.h> /* Function prototypes */ -static int option_open(struct usb_serial_port *port, struct file *filp); -static void option_close(struct usb_serial_port *port, struct file *filp); +static int option_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static void option_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); static int option_startup(struct usb_serial *serial); static void option_shutdown(struct usb_serial *serial); -static void option_rx_throttle(struct usb_serial_port *port); -static void option_rx_unthrottle(struct usb_serial_port *port); -static int option_write_room(struct usb_serial_port *port); +static int option_write_room(struct tty_struct *tty); static void option_instat_callback(struct urb *urb); -static int option_write(struct usb_serial_port *port, +static int option_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); - -static int option_chars_in_buffer(struct usb_serial_port *port); -static int option_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg); -static void option_set_termios(struct usb_serial_port *port, - struct ktermios *old); -static void option_break_ctl(struct usb_serial_port *port, int break_state); -static int option_tiocmget(struct usb_serial_port *port, struct file *file); -static int option_tiocmset(struct usb_serial_port *port, struct file *file, +static int option_chars_in_buffer(struct tty_struct *tty); +static void option_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static int option_tiocmget(struct tty_struct *tty, struct file *file); +static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); -static int option_send_setup(struct usb_serial_port *port); +static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 @@ -173,6 +169,7 @@ static int option_send_setup(struct usb_serial_port *port); #define DELL_VENDOR_ID 0x413C #define KYOCERA_VENDOR_ID 0x0c88 +#define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a #define ANYDATA_VENDOR_ID 0x16d5 @@ -305,6 +302,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ @@ -340,11 +338,7 @@ static struct usb_serial_driver option_1port_device = { .write = option_write, .write_room = option_write_room, .chars_in_buffer = option_chars_in_buffer, - .throttle = option_rx_throttle, - .unthrottle = option_rx_unthrottle, - .ioctl = option_ioctl, .set_termios = option_set_termios, - .break_ctl = option_break_ctl, .tiocmget = option_tiocmget, .tiocmset = option_tiocmset, .attach = option_startup, @@ -401,47 +395,32 @@ static int __init option_init(void) return 0; failed_driver_register: - usb_serial_deregister (&option_1port_device); + usb_serial_deregister(&option_1port_device); failed_1port_device_register: return retval; } static void __exit option_exit(void) { - usb_deregister (&option_driver); - usb_serial_deregister (&option_1port_device); + usb_deregister(&option_driver); + usb_serial_deregister(&option_1port_device); } module_init(option_init); module_exit(option_exit); -static void option_rx_throttle(struct usb_serial_port *port) -{ - dbg("%s", __func__); -} - -static void option_rx_unthrottle(struct usb_serial_port *port) -{ - dbg("%s", __func__); -} - -static void option_break_ctl(struct usb_serial_port *port, int break_state) -{ - /* Unfortunately, I don't know how to send a break */ - dbg("%s", __func__); -} - -static void option_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) +static void option_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s", __func__); /* Doesn't support option setting */ - tty_termios_copy_hw(port->tty->termios, old_termios); - option_send_setup(port); + tty_termios_copy_hw(tty->termios, old_termios); + option_send_setup(tty, port); } -static int option_tiocmget(struct usb_serial_port *port, struct file *file) +static int option_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; unsigned int value; struct option_port_private *portdata; @@ -457,9 +436,10 @@ static int option_tiocmget(struct usb_serial_port *port, struct file *file) return value; } -static int option_tiocmset(struct usb_serial_port *port, struct file *file, +static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct option_port_private *portdata; portdata = usb_get_serial_port_data(port); @@ -474,17 +454,11 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file, portdata->rts_state = 0; if (clear & TIOCM_DTR) portdata->dtr_state = 0; - return option_send_setup(port); -} - -static int option_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; + return option_send_setup(tty, port); } /* Write */ -static int option_write(struct usb_serial_port *port, +static int option_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct option_port_private *portdata; @@ -499,7 +473,7 @@ static int option_write(struct usb_serial_port *port, i = 0; left = count; - for (i=0; left > 0 && i < N_OUT_URB; i++) { + for (i = 0; left > 0 && i < N_OUT_URB; i++) { todo = left; if (todo > OUT_BUFLEN) todo = OUT_BUFLEN; @@ -520,7 +494,7 @@ static int option_write(struct usb_serial_port *port, usb_pipeendpoint(this_urb->pipe), i); /* send the data */ - memcpy (this_urb->transfer_buffer, buf, todo); + memcpy(this_urb->transfer_buffer, buf, todo); this_urb->transfer_buffer_length = todo; this_urb->dev = port->serial->dev; @@ -560,7 +534,7 @@ static void option_indat_callback(struct urb *urb) dbg("%s: nonzero status: %d on endpoint %02x.", __func__, status, endpoint); } else { - tty = port->tty; + tty = port->port.tty; if (urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); @@ -570,7 +544,7 @@ static void option_indat_callback(struct urb *urb) } /* Resubmit urb so we continue receiving */ - if (port->open_count && status != -ESHUTDOWN) { + if (port->port.count && status != -ESHUTDOWN) { err = usb_submit_urb(urb, GFP_ATOMIC); if (err) printk(KERN_ERR "%s: resubmit read urb failed. " @@ -611,7 +585,7 @@ static void option_instat_callback(struct urb *urb) struct usb_serial *serial = port->serial; dbg("%s", __func__); - dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata); + dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); if (status == 0) { struct usb_ctrlrequest *req_pkt = @@ -636,12 +610,12 @@ static void option_instat_callback(struct urb *urb) portdata->dsr_state = ((signals & 0x02) ? 1 : 0); portdata->ri_state = ((signals & 0x08) ? 1 : 0); - if (port->tty && !C_CLOCAL(port->tty) && + if (port->port.tty && !C_CLOCAL(port->port.tty) && old_dcd_state && !portdata->dcd_state) - tty_hangup(port->tty); + tty_hangup(port->port.tty); } else { dbg("%s: type %x req %x", __func__, - req_pkt->bRequestType,req_pkt->bRequest); + req_pkt->bRequestType, req_pkt->bRequest); } } else dbg("%s: error %d", __func__, status); @@ -656,8 +630,9 @@ static void option_instat_callback(struct urb *urb) } } -static int option_write_room(struct usb_serial_port *port) +static int option_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct option_port_private *portdata; int i; int data_len = 0; @@ -666,7 +641,7 @@ static int option_write_room(struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - for (i=0; i < N_OUT_URB; i++) { + for (i = 0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; if (this_urb && !test_bit(i, &portdata->out_busy)) data_len += OUT_BUFLEN; @@ -676,8 +651,9 @@ static int option_write_room(struct usb_serial_port *port) return data_len; } -static int option_chars_in_buffer(struct usb_serial_port *port) +static int option_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct option_port_private *portdata; int i; int data_len = 0; @@ -685,7 +661,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - for (i=0; i < N_OUT_URB; i++) { + for (i = 0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; /* FIXME: This locking is insufficient as this_urb may go unused during the test */ @@ -696,7 +672,8 @@ static int option_chars_in_buffer(struct usb_serial_port *port) return data_len; } -static int option_open(struct usb_serial_port *port, struct file *filp) +static int option_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct option_port_private *portdata; struct usb_serial *serial = port->serial; @@ -714,7 +691,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp) /* Reset low level data toggle and start reading from endpoints */ for (i = 0; i < N_IN_URB; i++) { urb = portdata->in_urbs[i]; - if (! urb) + if (!urb) continue; if (urb->dev != serial->dev) { dbg("%s: dev %p != %p", __func__, @@ -739,21 +716,23 @@ static int option_open(struct usb_serial_port *port, struct file *filp) /* Reset low level data toggle on out endpoints */ for (i = 0; i < N_OUT_URB; i++) { urb = portdata->out_urbs[i]; - if (! urb) + if (!urb) continue; urb->dev = serial->dev; /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ } - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; - option_send_setup(port); + option_send_setup(tty, port); - return (0); + return 0; } -static void option_close(struct usb_serial_port *port, struct file *filp) +static void option_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int i; struct usb_serial *serial = port->serial; @@ -768,7 +747,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp) if (serial->dev) { mutex_lock(&serial->disc_mutex); if (!serial->disconnected) - option_send_setup(port); + option_send_setup(tty, port); mutex_unlock(&serial->disc_mutex); /* Stop reading/writing urbs */ @@ -777,7 +756,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp) for (i = 0; i < N_OUT_URB; i++) usb_kill_urb(portdata->out_urbs[i]); } - port->tty = NULL; + port->port.tty = NULL; /* FIXME */ } /* Helper functions used by option_setup_urbs */ @@ -807,7 +786,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, /* Setup urbs */ static void option_setup_urbs(struct usb_serial *serial) { - int i,j; + int i, j; struct usb_serial_port *port; struct option_port_private *portdata; @@ -817,18 +796,22 @@ static void option_setup_urbs(struct usb_serial *serial) port = serial->port[i]; portdata = usb_get_serial_port_data(port); - /* Do indat endpoints first */ + /* Do indat endpoints first */ for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = option_setup_urb (serial, - port->bulk_in_endpointAddress, USB_DIR_IN, port, - portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); + portdata->in_urbs[j] = option_setup_urb(serial, + port->bulk_in_endpointAddress, + USB_DIR_IN, port, + portdata->in_buffer[j], + IN_BUFLEN, option_indat_callback); } /* outdat endpoints */ for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = option_setup_urb (serial, - port->bulk_out_endpointAddress, USB_DIR_OUT, port, - portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); + portdata->out_urbs[j] = option_setup_urb(serial, + port->bulk_out_endpointAddress, + USB_DIR_OUT, port, + portdata->out_buffer[j], + OUT_BUFLEN, option_outdat_callback); } } } @@ -839,7 +822,8 @@ static void option_setup_urbs(struct usb_serial *serial) * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN * CDC. */ -static int option_send_setup(struct usb_serial_port *port) +static int option_send_setup(struct tty_struct *tty, + struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct option_port_private *portdata; @@ -848,7 +832,7 @@ static int option_send_setup(struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - if (port->tty) { + if (tty) { int val = 0; if (portdata->dtr_state) val |= 0x01; @@ -856,10 +840,9 @@ static int option_send_setup(struct usb_serial_port *port) val |= 0x02; return usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT); + usb_rcvctrlpipe(serial->dev, 0), + 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); } - return 0; } @@ -879,7 +862,7 @@ static int option_startup(struct usb_serial *serial) if (!portdata) { dbg("%s: kmalloc for option_port_private (%d) failed!.", __func__, i); - return (1); + return 1; } for (j = 0; j < N_IN_URB; j++) { @@ -898,17 +881,15 @@ static int option_startup(struct usb_serial *serial) usb_set_serial_port_data(port, portdata); - if (! port->interrupt_in_urb) + if (!port->interrupt_in_urb) continue; err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (err) dbg("%s: submit irq_in urb failed %d", __func__, err); } - option_setup_urbs(serial); - - return (0); + return 0; bail_out_error2: for (j = 0; j < N_OUT_URB; j++) @@ -947,7 +928,8 @@ static void option_shutdown(struct usb_serial *serial) for (j = 0; j < N_IN_URB; j++) { if (portdata->in_urbs[j]) { usb_free_urb(portdata->in_urbs[j]); - free_page((unsigned long)portdata->in_buffer[j]); + free_page((unsigned long) + portdata->in_buffer[j]); portdata->in_urbs[j] = NULL; } } diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index a9625c180dc3..81db5715ee25 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -25,7 +25,8 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * TODO: * - implement correct flushing for ioctls and oti6858_close() @@ -49,7 +50,7 @@ #include <linux/spinlock.h> #include <linux/usb.h> #include <linux/usb/serial.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "oti6858.h" #define OTI6858_DESCRIPTION \ @@ -135,27 +136,28 @@ struct oti6858_control_pkt { #define OTI6858_CTRL_PKT_SIZE sizeof(struct oti6858_control_pkt) #define OTI6858_CTRL_EQUALS_PENDING(a, priv) \ - ( ((a)->divisor == (priv)->pending_setup.divisor) \ + (((a)->divisor == (priv)->pending_setup.divisor) \ && ((a)->control == (priv)->pending_setup.control) \ - && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) ) + && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt)) /* function prototypes */ -static int oti6858_open(struct usb_serial_port *port, struct file *filp); -static void oti6858_close(struct usb_serial_port *port, struct file *filp); -static void oti6858_set_termios(struct usb_serial_port *port, - struct ktermios *old); -static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, +static int oti6858_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void oti6858_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void oti6858_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static int oti6858_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void oti6858_read_int_callback(struct urb *urb); static void oti6858_read_bulk_callback(struct urb *urb); static void oti6858_write_bulk_callback(struct urb *urb); -static int oti6858_write(struct usb_serial_port *port, +static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); -static int oti6858_write_room(struct usb_serial_port *port); -static void oti6858_break_ctl(struct usb_serial_port *port, int break_state); -static int oti6858_chars_in_buffer(struct usb_serial_port *port); -static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file); -static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, +static int oti6858_write_room(struct tty_struct *tty); +static int oti6858_chars_in_buffer(struct tty_struct *tty); +static int oti6858_tiocmget(struct tty_struct *tty, struct file *file); +static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int oti6858_startup(struct usb_serial *serial); static void oti6858_shutdown(struct usb_serial *serial); @@ -184,7 +186,6 @@ static struct usb_serial_driver oti6858_device = { .close = oti6858_close, .write = oti6858_write, .ioctl = oti6858_ioctl, - .break_ctl = oti6858_break_ctl, .set_termios = oti6858_set_termios, .tiocmget = oti6858_tiocmget, .tiocmset = oti6858_tiocmset, @@ -220,7 +221,7 @@ struct oti6858_private { struct delayed_work delayed_setup_work; wait_queue_head_t intr_wait; - struct usb_serial_port *port; /* USB port with which associated */ + struct usb_serial_port *port; /* USB port with which associated */ }; #undef dbg @@ -229,7 +230,8 @@ struct oti6858_private { static void setup_line(struct work_struct *work) { - struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work); + struct oti6858_private *priv = container_of(work, + struct oti6858_private, delayed_setup_work.work); struct usb_serial_port *port = priv->port; struct oti6858_control_pkt *new_setup; unsigned long flags; @@ -237,10 +239,12 @@ static void setup_line(struct work_struct *work) dbg("%s(port = %d)", __func__, port->number); - if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) { + new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL); + if (new_setup == NULL) { dev_err(&port->dev, "%s(): out of memory!\n", __func__); /* we will try again */ - schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2)); + schedule_delayed_work(&priv->delayed_setup_work, + msecs_to_jiffies(2)); return; } @@ -256,7 +260,8 @@ static void setup_line(struct work_struct *work) dev_err(&port->dev, "%s(): error reading status\n", __func__); kfree(new_setup); /* we will try again */ - schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2)); + schedule_delayed_work(&priv->delayed_setup_work, + msecs_to_jiffies(2)); return; } @@ -297,7 +302,8 @@ static void setup_line(struct work_struct *work) void send_data(struct work_struct *work) { - struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work); + struct oti6858_private *priv = container_of(work, + struct oti6858_private, delayed_write_work.work); struct usb_serial_port *port = priv->port; int count = 0, result; unsigned long flags; @@ -308,7 +314,8 @@ void send_data(struct work_struct *work) spin_lock_irqsave(&priv->lock, flags); if (priv->flags.write_urb_in_use) { spin_unlock_irqrestore(&priv->lock, flags); - schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2)); + schedule_delayed_work(&priv->delayed_write_work, + msecs_to_jiffies(2)); return; } priv->flags.write_urb_in_use = 1; @@ -359,8 +366,8 @@ void send_data(struct work_struct *work) static int oti6858_startup(struct usb_serial *serial) { - struct usb_serial_port *port = serial->port[0]; - struct oti6858_private *priv; + struct usb_serial_port *port = serial->port[0]; + struct oti6858_private *priv; int i; for (i = 0; i < serial->num_ports; ++i) { @@ -375,8 +382,8 @@ static int oti6858_startup(struct usb_serial *serial) spin_lock_init(&priv->lock); init_waitqueue_head(&priv->intr_wait); -// INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); -// INIT_WORK(&priv->write_work, send_data, serial->port[i]); +/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */ +/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */ priv->port = port; INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); @@ -395,7 +402,7 @@ static int oti6858_startup(struct usb_serial *serial) return -ENOMEM; } -static int oti6858_write(struct usb_serial_port *port, +static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct oti6858_private *priv = usb_get_serial_port_data(port); @@ -413,8 +420,9 @@ static int oti6858_write(struct usb_serial_port *port, return count; } -static int oti6858_write_room(struct usb_serial_port *port) +static int oti6858_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct oti6858_private *priv = usb_get_serial_port_data(port); int room = 0; unsigned long flags; @@ -428,8 +436,9 @@ static int oti6858_write_room(struct usb_serial_port *port) return room; } -static int oti6858_chars_in_buffer(struct usb_serial_port *port) +static int oti6858_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct oti6858_private *priv = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; @@ -443,8 +452,8 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port) return chars; } -static void oti6858_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) +static void oti6858_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct oti6858_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -455,22 +464,22 @@ static void oti6858_set_termios(struct usb_serial_port *port, dbg("%s(port = %d)", __func__, port->number); - if (!port->tty || !port->tty->termios) { + if (!tty) { dbg("%s(): no tty structures", __func__); return; } spin_lock_irqsave(&priv->lock, flags); if (!priv->flags.termios_initialized) { - *(port->tty->termios) = tty_std_termios; - port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; + tty->termios->c_ispeed = 38400; + tty->termios->c_ospeed = 38400; priv->flags.termios_initialized = 1; - port->tty->termios->c_ispeed = 38400; - port->tty->termios->c_ospeed = 38400; } spin_unlock_irqrestore(&priv->lock, flags); - cflag = port->tty->termios->c_cflag; + cflag = tty->termios->c_cflag; spin_lock_irqsave(&priv->lock, flags); divisor = priv->pending_setup.divisor; @@ -480,19 +489,19 @@ static void oti6858_set_termios(struct usb_serial_port *port, frame_fmt &= ~FMT_DATA_BITS_MASK; switch (cflag & CSIZE) { - case CS5: - frame_fmt |= FMT_DATA_BITS_5; - break; - case CS6: - frame_fmt |= FMT_DATA_BITS_6; - break; - case CS7: - frame_fmt |= FMT_DATA_BITS_7; - break; - default: - case CS8: - frame_fmt |= FMT_DATA_BITS_8; - break; + case CS5: + frame_fmt |= FMT_DATA_BITS_5; + break; + case CS6: + frame_fmt |= FMT_DATA_BITS_6; + break; + case CS7: + frame_fmt |= FMT_DATA_BITS_7; + break; + default: + case CS8: + frame_fmt |= FMT_DATA_BITS_8; + break; } /* manufacturer claims that this device can work with baud rates @@ -500,7 +509,7 @@ static void oti6858_set_termios(struct usb_serial_port *port, * guarantee that any other baud rate will work (especially * the higher ones) */ - br = tty_get_baud_rate(port->tty); + br = tty_get_baud_rate(tty); if (br == 0) { divisor = 0; } else { @@ -511,23 +520,21 @@ static void oti6858_set_termios(struct usb_serial_port *port, new_divisor = (96000000 + 8 * br) / (16 * br); real_br = 96000000 / (16 * new_divisor); divisor = cpu_to_le16(new_divisor); - tty_encode_baud_rate(port->tty, real_br, real_br); + tty_encode_baud_rate(tty, real_br, real_br); } frame_fmt &= ~FMT_STOP_BITS_MASK; - if ((cflag & CSTOPB) != 0) { + if ((cflag & CSTOPB) != 0) frame_fmt |= FMT_STOP_BITS_2; - } else { + else frame_fmt |= FMT_STOP_BITS_1; - } frame_fmt &= ~FMT_PARITY_MASK; if ((cflag & PARENB) != 0) { - if ((cflag & PARODD) != 0) { + if ((cflag & PARODD) != 0) frame_fmt |= FMT_PARITY_ODD; - } else { + else frame_fmt |= FMT_PARITY_EVEN; - } } else { frame_fmt |= FMT_PARITY_NONE; } @@ -564,7 +571,8 @@ static void oti6858_set_termios(struct usb_serial_port *port, spin_unlock_irqrestore(&priv->lock, flags); } -static int oti6858_open(struct usb_serial_port *port, struct file *filp) +static int oti6858_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct oti6858_private *priv = usb_get_serial_port_data(port); struct ktermios tmp_termios; @@ -578,10 +586,11 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp) usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); - if (port->open_count != 1) + if (port->port.count != 1) return 0; - if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) { + buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL); + if (buf == NULL) { dev_err(&port->dev, "%s(): out of memory!\n", __func__); return -ENOMEM; } @@ -617,18 +626,19 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp) if (result != 0) { dev_err(&port->dev, "%s(): usb_submit_urb() failed" " with error %d\n", __func__, result); - oti6858_close(port, NULL); + oti6858_close(tty, port, NULL); return -EPROTO; } /* setup termios */ - if (port->tty) - oti6858_set_termios(port, &tmp_termios); + if (tty) + oti6858_set_termios(tty, port, &tmp_termios); return 0; } -static void oti6858_close(struct usb_serial_port *port, struct file *filp) +static void oti6858_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct oti6858_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -641,7 +651,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp) spin_lock_irqsave(&priv->lock, flags); timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */ init_waitqueue_entry(&wait, current); - add_wait_queue(&port->tty->write_wait, &wait); + add_wait_queue(&tty->write_wait, &wait); dbg("%s(): entering wait loop", __func__); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -654,7 +664,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp) spin_lock_irqsave(&priv->lock, flags); } set_current_state(TASK_RUNNING); - remove_wait_queue(&port->tty->write_wait, &wait); + remove_wait_queue(&tty->write_wait, &wait); dbg("%s(): after wait loop", __func__); /* clear out any remaining data in the buffer */ @@ -669,7 +679,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp) /* data is in the buffer to compute a delay */ /* that is not unnecessarily long) */ /* FIXME - bps = tty_get_baud_rate(port->tty); + bps = tty_get_baud_rate(tty); if (bps > 1200) timeout = max((HZ*2560)/bps,HZ/10); else @@ -690,7 +700,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp) usb_kill_urb(port->interrupt_in_urb); /* - if (port->tty && (port->tty->termios->c_cflag) & HUPCL) { + if (tty && (tty->termios->c_cflag) & HUPCL) { // drop DTR and RTS spin_lock_irqsave(&priv->lock, flags); priv->pending_setup.control &= ~CONTROL_MASK; @@ -699,9 +709,10 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp) */ } -static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, +static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct oti6858_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 control; @@ -724,16 +735,16 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, if ((clear & TIOCM_DTR) != 0) control &= ~CONTROL_DTR_HIGH; - if (control != priv->pending_setup.control) { + if (control != priv->pending_setup.control) priv->pending_setup.control = control; - } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return 0; } -static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file) +static int oti6858_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct oti6858_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned pin_state; @@ -779,7 +790,8 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) spin_unlock_irqrestore(&priv->lock, flags); while (1) { - wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev); + wait_event_interruptible(priv->intr_wait, + priv->status.pin_state != prev); if (signal_pending(current)) return -ERESTARTSYS; @@ -789,12 +801,11 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) changed = prev ^ status; /* FIXME: check if this is correct (active high/low) */ - if ( ((arg & TIOCM_RNG) && (changed & PIN_RI)) || - ((arg & TIOCM_DSR) && (changed & PIN_DSR)) || - ((arg & TIOCM_CD) && (changed & PIN_DCD)) || - ((arg & TIOCM_CTS) && (changed & PIN_CTS))) { - return 0; - } + if (((arg & TIOCM_RNG) && (changed & PIN_RI)) || + ((arg & TIOCM_DSR) && (changed & PIN_DSR)) || + ((arg & TIOCM_CD) && (changed & PIN_DCD)) || + ((arg & TIOCM_CTS) && (changed & PIN_CTS))) + return 0; prev = status; } @@ -802,56 +813,25 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return 0; } -static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, +static int oti6858_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - void __user *user_arg = (void __user *) arg; - unsigned int x; + struct usb_serial_port *port = tty->driver_data; dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)", __func__, port->number, cmd, arg); switch (cmd) { - case TIOCMBIS: - if (copy_from_user(&x, user_arg, sizeof(x))) - return -EFAULT; - return oti6858_tiocmset(port, NULL, x, 0); - - case TIOCMBIC: - if (copy_from_user(&x, user_arg, sizeof(x))) - return -EFAULT; - return oti6858_tiocmset(port, NULL, 0, x); - - case TIOCMIWAIT: - dbg("%s(): TIOCMIWAIT", __func__); - return wait_modem_info(port, arg); - - default: - dbg("%s(): 0x%04x not supported", __func__, cmd); - break; + case TIOCMIWAIT: + dbg("%s(): TIOCMIWAIT", __func__); + return wait_modem_info(port, arg); + default: + dbg("%s(): 0x%04x not supported", __func__, cmd); + break; } - return -ENOIOCTLCMD; } -static void oti6858_break_ctl(struct usb_serial_port *port, int break_state) -{ - int state; - - dbg("%s(port = %d)", __func__, port->number); - - state = (break_state == 0) ? 0 : 1; - dbg("%s(): turning break %s", __func__, state ? "on" : "off"); - - /* FIXME */ -/* - result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), - BREAK_REQUEST, BREAK_REQUEST_TYPE, state, - 0, NULL, 0, 100); - if (result != 0) - dbg("%s(): error sending break", __func__); - */ -} static void oti6858_shutdown(struct usb_serial *serial) { @@ -964,7 +944,7 @@ static void oti6858_read_int_callback(struct urb *urb) spin_lock_irqsave(&priv->lock, flags); if (priv->flags.write_urb_in_use == 0 && oti6858_buf_data_avail(priv->buf) != 0) { - schedule_delayed_work(&priv->delayed_write_work,0); + schedule_delayed_work(&priv->delayed_write_work, 0); resubmit = 0; } spin_unlock_irqrestore(&priv->lock, flags); @@ -973,7 +953,7 @@ static void oti6858_read_int_callback(struct urb *urb) if (resubmit) { int result; -// dbg("%s(): submitting interrupt urb", __func__); +/* dbg("%s(): submitting interrupt urb", __func__); */ urb->dev = port->serial->dev; result = usb_submit_urb(urb, GFP_ATOMIC); if (result != 0) { @@ -1002,14 +982,16 @@ static void oti6858_read_bulk_callback(struct urb *urb) spin_unlock_irqrestore(&priv->lock, flags); if (status != 0) { - if (!port->open_count) { + if (!port->port.count) { dbg("%s(): port is closed, exiting", __func__); return; } /* if (status == -EPROTO) { - // PL2303 mysteriously fails with -EPROTO reschedule the read - dbg("%s - caught -EPROTO, resubmitting the urb", __func__); + * PL2303 mysteriously fails with -EPROTO reschedule + the read * + dbg("%s - caught -EPROTO, resubmitting the urb", + __func__); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); @@ -1020,14 +1002,14 @@ static void oti6858_read_bulk_callback(struct urb *urb) return; } - tty = port->tty; + tty = port->port.tty; if (tty != NULL && urb->actual_length > 0) { tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } - // schedule the interrupt urb if we are still open */ - if (port->open_count != 0) { + /* schedule the interrupt urb if we are still open */ + if (port->port.count != 0) { port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result != 0) { @@ -1078,7 +1060,7 @@ static void oti6858_write_bulk_callback(struct urb *urb) priv->flags.write_urb_in_use = 0; - // schedule the interrupt urb if we are still open */ + /* schedule the interrupt urb if we are still open */ port->interrupt_in_urb->dev = port->serial->dev; dbg("%s(): submitting interrupt urb", __func__); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); @@ -1153,7 +1135,7 @@ static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb) { if (pb == NULL) return 0; - return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); + return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size; } /* @@ -1166,7 +1148,7 @@ static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb) { if (pb == NULL) return 0; - return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); + return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size; } /* @@ -1253,13 +1235,12 @@ static int __init oti6858_init(void) { int retval; - if ((retval = usb_serial_register(&oti6858_device)) == 0) { - if ((retval = usb_register(&oti6858_driver)) != 0) + retval = usb_serial_register(&oti6858_device); + if (retval == 0) { + retval = usb_register(&oti6858_driver); + if (retval) usb_serial_deregister(&oti6858_device); - else - return 0; } - return retval; } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2a0dd1b50dc4..2c9c446ad625 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -10,7 +10,8 @@ * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * */ @@ -25,7 +26,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "pl2303.h" @@ -116,7 +117,7 @@ static struct usb_driver pl2303_driver = { #define CONTROL_RTS 0x02 #define BREAK_REQUEST_TYPE 0x21 -#define BREAK_REQUEST 0x23 +#define BREAK_REQUEST 0x23 #define BREAK_ON 0xffff #define BREAK_OFF 0x0000 @@ -222,7 +223,7 @@ static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) if (pb == NULL) return 0; - return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); + return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size; } /* @@ -236,7 +237,7 @@ static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) if (pb == NULL) return 0; - return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); + return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size; } /* @@ -395,7 +396,7 @@ static int pl2303_startup(struct usb_serial *serial) cleanup: kfree(buf); - for (--i; i>=0; --i) { + for (--i; i >= 0; --i) { priv = usb_get_serial_port_data(serial->port[i]); pl2303_buf_free(priv->buf); kfree(priv); @@ -407,7 +408,7 @@ cleanup: static int set_control_lines(struct usb_device *dev, u8 value) { int retval; - + retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, value, 0, NULL, 0, 100); @@ -452,14 +453,14 @@ static void pl2303_send(struct usb_serial_port *port) dev_err(&port->dev, "%s - failed submitting write urb," " error %d\n", __func__, result); priv->write_urb_in_use = 0; - // TODO: reschedule pl2303_send + /* TODO: reschedule pl2303_send */ } usb_serial_port_softint(port); } -static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf, - int count) +static int pl2303_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -478,8 +479,9 @@ static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf, return count; } -static int pl2303_write_room(struct usb_serial_port *port) +static int pl2303_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct pl2303_private *priv = usb_get_serial_port_data(port); int room = 0; unsigned long flags; @@ -494,8 +496,9 @@ static int pl2303_write_room(struct usb_serial_port *port) return room; } -static int pl2303_chars_in_buffer(struct usb_serial_port *port) +static int pl2303_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct pl2303_private *priv = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; @@ -510,8 +513,8 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port) return chars; } -static void pl2303_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) +static void pl2303_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); @@ -526,11 +529,10 @@ static void pl2303_set_termios(struct usb_serial_port *port, spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { - *(port->tty->termios) = tty_std_termios; - port->tty->termios->c_cflag = B9600 | CS8 | CREAD | - HUPCL | CLOCAL; - port->tty->termios->c_ispeed = 9600; - port->tty->termios->c_ospeed = 9600; + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + tty->termios->c_ispeed = 9600; + tty->termios->c_ospeed = 9600; priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); @@ -539,16 +541,16 @@ static void pl2303_set_termios(struct usb_serial_port *port, serial settings even to the same values as before. Thus we actually need to filter in this specific case */ - if (!tty_termios_hw_change(port->tty->termios, old_termios)) + if (!tty_termios_hw_change(tty->termios, old_termios)) return; - cflag = port->tty->termios->c_cflag; + cflag = tty->termios->c_cflag; buf = kzalloc(7, GFP_KERNEL); if (!buf) { dev_err(&port->dev, "%s - out of memory.\n", __func__); /* Report back no change occurred */ - *port->tty->termios = *old_termios; + *tty->termios = *old_termios; return; } @@ -560,16 +562,24 @@ static void pl2303_set_termios(struct usb_serial_port *port, if (cflag & CSIZE) { switch (cflag & CSIZE) { - case CS5: buf[6] = 5; break; - case CS6: buf[6] = 6; break; - case CS7: buf[6] = 7; break; - default: - case CS8: buf[6] = 8; break; + case CS5: + buf[6] = 5; + break; + case CS6: + buf[6] = 6; + break; + case CS7: + buf[6] = 7; + break; + default: + case CS8: + buf[6] = 8; + break; } dbg("%s - data bits = %d", __func__, buf[6]); } - baud = tty_get_baud_rate(port->tty);; + baud = tty_get_baud_rate(tty); dbg("%s - baud = %d", __func__, baud); if (baud) { buf[0] = baud & 0xff; @@ -646,12 +656,13 @@ static void pl2303_set_termios(struct usb_serial_port *port, /* FIXME: Need to read back resulting baud rate */ if (baud) - tty_encode_baud_rate(port->tty, baud, baud); + tty_encode_baud_rate(tty, baud, baud); kfree(buf); } -static void pl2303_close(struct usb_serial_port *port, struct file *filp) +static void pl2303_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -666,7 +677,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) spin_lock_irqsave(&priv->lock, flags); timeout = PL2303_CLOSING_WAIT; init_waitqueue_entry(&wait, current); - add_wait_queue(&port->tty->write_wait, &wait); + add_wait_queue(&tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (pl2303_buf_data_avail(priv->buf) == 0 || @@ -678,7 +689,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) spin_lock_irqsave(&priv->lock, flags); } set_current_state(TASK_RUNNING); - remove_wait_queue(&port->tty->write_wait, &wait); + remove_wait_queue(&tty->write_wait, &wait); /* clear out any remaining data in the buffer */ pl2303_buf_clear(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); @@ -690,9 +701,9 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) /* for lower rates we should really know how much */ /* data is in the buffer to compute a delay */ /* that is not unnecessarily long) */ - bps = tty_get_baud_rate(port->tty); + bps = tty_get_baud_rate(tty); if (bps > 1200) - timeout = max((HZ*2560)/bps,HZ/10); + timeout = max((HZ*2560)/bps, HZ/10); else timeout = 2*HZ; schedule_timeout_interruptible(timeout); @@ -703,8 +714,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; + if (tty) { + c_cflag = tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop DTR and RTS */ spin_lock_irqsave(&priv->lock, flags); @@ -715,7 +726,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) } } -static int pl2303_open(struct usb_serial_port *port, struct file *filp) +static int pl2303_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; @@ -734,11 +746,10 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) } /* Setup termios */ - if (port->tty) { - pl2303_set_termios(port, &tmp_termios); - } + if (tty) + pl2303_set_termios(tty, port, &tmp_termios); - //FIXME: need to assert RTS and DTR if CRTSCTS off + /* FIXME: need to assert RTS and DTR if CRTSCTS off */ dbg("%s - submitting read urb", __func__); port->read_urb->dev = serial->dev; @@ -746,7 +757,7 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) if (result) { dev_err(&port->dev, "%s - failed submitting read urb," " error %d\n", __func__, result); - pl2303_close(port, NULL); + pl2303_close(tty, port, NULL); return -EPROTO; } @@ -756,15 +767,16 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) if (result) { dev_err(&port->dev, "%s - failed submitting interrupt urb," " error %d\n", __func__, result); - pl2303_close(port, NULL); + pl2303_close(tty, port, NULL); return -EPROTO; } return 0; } -static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file, +static int pl2303_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 control; @@ -787,8 +799,9 @@ static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file, return set_control_lines(port->serial->dev, control); } -static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file) +static int pl2303_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int mcr; @@ -839,12 +852,12 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) status = priv->line_status; spin_unlock_irqrestore(&priv->lock, flags); - changed=prevstatus^status; + changed = prevstatus ^ status; if (((arg & TIOCM_RNG) && (changed & UART_RING)) || ((arg & TIOCM_DSR) && (changed & UART_DSR)) || ((arg & TIOCM_CD) && (changed & UART_DCD)) || - ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) { + ((arg & TIOCM_CTS) && (changed & UART_CTS))) { return 0; } prevstatus = status; @@ -853,26 +866,26 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return 0; } -static int pl2303_ioctl(struct usb_serial_port *port, struct file *file, +static int pl2303_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); switch (cmd) { - case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); - return wait_modem_info(port, arg); - - default: - dbg("%s not supported = 0x%04x", __func__, cmd); - break; + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + return wait_modem_info(port, arg); + default: + dbg("%s not supported = 0x%04x", __func__, cmd); + break; } - return -ENOIOCTLCMD; } -static void pl2303_break_ctl(struct usb_serial_port *port, int break_state) +static void pl2303_break_ctl(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; u16 state; int result; @@ -883,7 +896,8 @@ static void pl2303_break_ctl(struct usb_serial_port *port, int break_state) state = BREAK_OFF; else state = BREAK_ON; - dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on"); + dbg("%s - turning break %s", __func__, + state == BREAK_OFF ? "off" : "on"); result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), BREAK_REQUEST, BREAK_REQUEST_TYPE, state, @@ -937,7 +951,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port, if (actual_length < length) return; - /* Save off the uart status for others to look at */ + /* Save off the uart status for others to look at */ spin_lock_irqsave(&priv->lock, flags); priv->line_status = data[status_idx]; spin_unlock_irqrestore(&priv->lock, flags); @@ -1001,7 +1015,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) if (status) { dbg("%s - urb status = %d", __func__, status); - if (!port->open_count) { + if (!port->port.count) { dbg("%s - port is closed, exiting.", __func__); return; } @@ -1036,7 +1050,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) /* break takes precedence over parity, */ /* which takes precedence over framing errors */ - if (line_status & UART_BREAK_ERROR ) + if (line_status & UART_BREAK_ERROR) tty_flag = TTY_BREAK; else if (line_status & UART_PARITY_ERROR) tty_flag = TTY_PARITY; @@ -1044,7 +1058,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) tty_flag = TTY_FRAME; dbg("%s - tty_flag = %d", __func__, tty_flag); - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ @@ -1056,7 +1070,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) } /* Schedule the next read _if_ we are still open */ - if (port->open_count) { + if (port->port.count) { urb->dev = port->serial->dev; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 94bddf06ea4f..def52d07a4ea 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -13,24 +13,25 @@ * Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com> */ -/* - * The encapsultaion is designed to overcome difficulties with some USB hardware. +/* + * The encapsultaion is designed to overcome difficulties with some USB + * hardware. * * While the USB protocol has a CRC over the data while in transit, i.e. while - * being carried over the bus, there is no end to end protection. If the hardware - * has any problems getting the data into or out of the USB transmit and receive - * FIFO's then data can be lost. + * being carried over the bus, there is no end to end protection. If the + * hardware has any problems getting the data into or out of the USB transmit + * and receive FIFO's then data can be lost. * - * This protocol adds a two byte trailer to each USB packet to specify the number - * of bytes of valid data and a 10 bit CRC that will allow the receiver to verify - * that the entire USB packet was received without error. + * This protocol adds a two byte trailer to each USB packet to specify the + * number of bytes of valid data and a 10 bit CRC that will allow the receiver + * to verify that the entire USB packet was received without error. * - * Because in this case the sender and receiver are the class and function drivers - * there is now end to end protection. + * Because in this case the sender and receiver are the class and function + * drivers there is now end to end protection. * - * There is an additional option that can be used to force all transmitted packets - * to be padded to the maximum packet size. This provides a work around for some - * devices which have problems with small USB packets. + * There is an additional option that can be used to force all transmitted + * packets to be padded to the maximum packet size. This provides a work + * around for some devices which have problems with small USB packets. * * Assuming a packetsize of N: * @@ -44,11 +45,12 @@ * | Data Length | 10 bit CRC | * + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 + * - * The 10 bit CRC is computed across the sent data, followed by the trailer with - * the length set and the CRC set to zero. The CRC is then OR'd into the trailer. + * The 10 bit CRC is computed across the sent data, followed by the trailer + * with the length set and the CRC set to zero. The CRC is then OR'd into + * the trailer. * - * When received a 10 bit CRC is computed over the entire frame including the trailer - * and should be equal to zero. + * When received a 10 bit CRC is computed over the entire frame including + * the trailer and should be equal to zero. * * Two module parameters are used to control the encapsulation, if both are * turned of the module works as a simple serial device with NO @@ -69,7 +71,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -86,12 +88,12 @@ static int padded = CONFIG_USB_SERIAL_SAFE_PADDED; #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com" #define DRIVER_DESC "USB Safe Encapsulated Serial" -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_DESCRIPTION (DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -static __u16 vendor; // no default -static __u16 product; // no default +static __u16 vendor; /* no default */ +static __u16 product; /* no default */ module_param(vendor, ushort, 0); MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)"); module_param(product, ushort, 0); @@ -122,30 +124,31 @@ MODULE_PARM_DESC(padded, "Pad to full wMaxPacketSize On/Off"); #define LINEO_SAFESERIAL_CRC_PADDED 0x02 -#define MY_USB_DEVICE(vend,prod,dc,ic,isc) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS | \ - USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, \ - .idVendor = (vend), \ - .idProduct = (prod),\ - .bDeviceClass = (dc),\ - .bInterfaceClass = (ic), \ - .bInterfaceSubClass = (isc), +#define MY_USB_DEVICE(vend, prod, dc, ic, isc) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_DEV_CLASS | \ + USB_DEVICE_ID_MATCH_INT_CLASS | \ + USB_DEVICE_ID_MATCH_INT_SUBCLASS, \ + .idVendor = (vend), \ + .idProduct = (prod),\ + .bDeviceClass = (dc),\ + .bInterfaceClass = (ic), \ + .bInterfaceSubClass = (isc), static struct usb_device_id id_table[] = { - {MY_USB_DEVICE (0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Itsy - {MY_USB_DEVICE (0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Calypso - {MY_USB_DEVICE (0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Iris - {MY_USB_DEVICE (0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie - {MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie - {MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie - {MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Sharp tmp - // extra null entry for module - // vendor/produc parameters - {MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, - {} // terminating entry + {MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Itsy */ + {MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Calypso */ + {MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Iris */ + {MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */ + {MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */ + {MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */ + {MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Sharp tmp */ + /* extra null entry for module vendor/produc parameters */ + {MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, + {} /* terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver safe_driver = { .name = "safe_serial", @@ -156,29 +159,45 @@ static struct usb_driver safe_driver = { }; static const __u16 crc10_table[256] = { - 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe, - 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf, - 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c, - 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad, - 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a, - 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b, - 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158, - 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169, - 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076, - 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047, - 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014, - 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025, - 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2, - 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083, - 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0, - 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1, + 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, + 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe, + 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, + 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf, + 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, + 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c, + 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, + 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad, + 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, + 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a, + 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, + 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b, + 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, + 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158, + 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, + 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169, + 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, + 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076, + 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, + 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047, + 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, + 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014, + 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, + 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025, + 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, + 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2, + 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, + 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083, + 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, + 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0, + 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, + 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1, }; -#define CRC10_INITFCS 0x000 // Initial FCS value -#define CRC10_GOODFCS 0x000 // Good final FCS value -#define CRC10_FCS(fcs, c) ( (((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c)) +#define CRC10_INITFCS 0x000 /* Initial FCS value */ +#define CRC10_GOODFCS 0x000 /* Good final FCS value */ +#define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c)) -/** +/** * fcs_compute10 - memcpy and calculate 10 bit CRC across buffer * @sp: pointer to buffer * @len: number of bytes @@ -187,13 +206,13 @@ static const __u16 crc10_table[256] = { * Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return * new 10 bit FCS. */ -static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs) +static __u16 __inline__ fcs_compute10(unsigned char *sp, int len, __u16 fcs) { - for (; len-- > 0; fcs = CRC10_FCS (fcs, *sp++)); + for (; len-- > 0; fcs = CRC10_FCS(fcs, *sp++)); return fcs; } -static void safe_read_bulk_callback (struct urb *urb) +static void safe_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; @@ -201,7 +220,7 @@ static void safe_read_bulk_callback (struct urb *urb) int result; int status = urb->status; - dbg ("%s", __func__); + dbg("%s", __func__); if (status) { dbg("%s - nonzero read bulk status received: %d", @@ -209,76 +228,82 @@ static void safe_read_bulk_callback (struct urb *urb) return; } - dbg ("safe_read_bulk_callback length: %d", port->read_urb->actual_length); + dbg("safe_read_bulk_callback length: %d", + port->read_urb->actual_length); #ifdef ECHO_RCV { int i; unsigned char *cp = port->read_urb->transfer_buffer; for (i = 0; i < port->read_urb->actual_length; i++) { - if ((i % 32) == 0) { - printk ("\nru[%02x] ", i); - } - printk ("%02x ", *cp++); + if ((i % 32) == 0) + printk("\nru[%02x] ", i); + printk("%02x ", *cp++); } - printk ("\n"); + printk("\n"); } #endif if (safe) { __u16 fcs; - if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) { + fcs = fcs_compute10(data, length, CRC10_INITFCS); + if (!fcs) { int actual_length = data[length - 2] >> 2; if (actual_length <= (length - 2)) { - info ("%s - actual: %d", __func__, actual_length); - tty_insert_flip_string(port->tty, data, actual_length); - tty_flip_buffer_push (port->tty); + info("%s - actual: %d", __func__, + actual_length); + tty_insert_flip_string(port->port.tty, + data, actual_length); + tty_flip_buffer_push(port->port.tty); } else { - err ("%s - inconsistent lengths %d:%d", __func__, - actual_length, length); + err("%s - inconsistent lengths %d:%d", + __func__, actual_length, length); } } else { - err ("%s - bad CRC %x", __func__, fcs); + err("%s - bad CRC %x", __func__, fcs); } } else { - tty_insert_flip_string(port->tty, data, length); - tty_flip_buffer_push (port->tty); + tty_insert_flip_string(port->port.tty, data, length); + tty_flip_buffer_push(port->port.tty); } /* Continue trying to always read */ - usb_fill_bulk_urb (urb, port->serial->dev, - usb_rcvbulkpipe (port->serial->dev, port->bulk_in_endpointAddress), - urb->transfer_buffer, urb->transfer_buffer_length, - safe_read_bulk_callback, port); - - if ((result = usb_submit_urb (urb, GFP_ATOMIC))) { - err ("%s - failed resubmitting read urb, error %d", __func__, result); + usb_fill_bulk_urb(urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + urb->transfer_buffer, urb->transfer_buffer_length, + safe_read_bulk_callback, port); + + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + err("%s - failed resubmitting read urb, error %d", + __func__, result); /* FIXME: Need a mechanism to retry later if this happens */ - } } -static int safe_write (struct usb_serial_port *port, const unsigned char *buf, int count) +static int safe_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { unsigned char *data; int result; int i; int packet_length; - dbg ("safe_write port: %p %d urb: %p count: %d", port, port->number, port->write_urb, - count); + dbg("safe_write port: %p %d urb: %p count: %d", + port, port->number, port->write_urb, count); if (!port->write_urb) { - dbg ("%s - write urb NULL", __func__); + dbg("%s - write urb NULL", __func__); return 0; } - dbg ("safe_write write_urb: %d transfer_buffer_length", + dbg("safe_write write_urb: %d transfer_buffer_length", port->write_urb->transfer_buffer_length); if (!port->write_urb->transfer_buffer_length) { - dbg ("%s - write urb transfer_buffer_length zero", __func__); + dbg("%s - write urb transfer_buffer_length zero", __func__); return 0; } if (count == 0) { - dbg ("%s - write request of 0 bytes", __func__); + dbg("%s - write request of 0 bytes", __func__); return 0; } spin_lock_bh(&port->lock); @@ -290,85 +315,85 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i port->write_urb_busy = 1; spin_unlock_bh(&port->lock); - packet_length = port->bulk_out_size; // get max packetsize + packet_length = port->bulk_out_size; /* get max packetsize */ - i = packet_length - (safe ? 2 : 0); // get bytes to send + i = packet_length - (safe ? 2 : 0); /* get bytes to send */ count = (count > i) ? i : count; - // get the data into the transfer buffer + /* get the data into the transfer buffer */ data = port->write_urb->transfer_buffer; - memset (data, '0', packet_length); + memset(data, '0', packet_length); - memcpy (data, buf, count); + memcpy(data, buf, count); if (safe) { __u16 fcs; - // pad if necessary - if (!padded) { + /* pad if necessary */ + if (!padded) packet_length = count + 2; - } - // set count + /* set count */ data[packet_length - 2] = count << 2; data[packet_length - 1] = 0; - // compute fcs and insert into trailer - fcs = fcs_compute10 (data, packet_length, CRC10_INITFCS); + /* compute fcs and insert into trailer */ + fcs = fcs_compute10(data, packet_length, CRC10_INITFCS); data[packet_length - 2] |= fcs >> 8; data[packet_length - 1] |= fcs & 0xff; - // set length to send + /* set length to send */ port->write_urb->transfer_buffer_length = packet_length; } else { port->write_urb->transfer_buffer_length = count; } - usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer); + usb_serial_debug_data(debug, &port->dev, __func__, count, + port->write_urb->transfer_buffer); #ifdef ECHO_TX { int i; unsigned char *cp = port->write_urb->transfer_buffer; for (i = 0; i < port->write_urb->transfer_buffer_length; i++) { - if ((i % 32) == 0) { - printk ("\nsu[%02x] ", i); - } - printk ("%02x ", *cp++); + if ((i % 32) == 0) + printk("\nsu[%02x] ", i); + printk("%02x ", *cp++); } - printk ("\n"); + printk("\n"); } #endif port->write_urb->dev = port->serial->dev; - if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { + result = usb_submit_urb(port->write_urb, GFP_KERNEL); + if (result) { port->write_urb_busy = 0; - err ("%s - failed submitting write urb, error %d", __func__, result); + err("%s - failed submitting write urb, error %d", + __func__, result); return 0; } - dbg ("%s urb: %p submitted", __func__, port->write_urb); + dbg("%s urb: %p submitted", __func__, port->write_urb); - return (count); + return count; } -static int safe_write_room (struct usb_serial_port *port) +static int safe_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; int room = 0; /* Default: no room */ unsigned long flags; - dbg ("%s", __func__); + dbg("%s", __func__); spin_lock_irqsave(&port->lock, flags); if (port->write_urb_busy) room = port->bulk_out_size - (safe ? 2 : 0); spin_unlock_irqrestore(&port->lock, flags); - if (room) { - dbg ("safe_write_room returns %d", room); - } - + if (room) + dbg("safe_write_room returns %d", room); return room; } -static int safe_startup (struct usb_serial *serial) +static int safe_startup(struct usb_serial *serial) { switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) { case LINEO_SAFESERIAL_CRC: @@ -396,17 +421,18 @@ static struct usb_serial_driver safe_device = { .attach = safe_startup, }; -static int __init safe_init (void) +static int __init safe_init(void) { int i, retval; - info (DRIVER_VERSION " " DRIVER_AUTHOR); - info (DRIVER_DESC); - info ("vendor: %x product: %x safe: %d padded: %d\n", vendor, product, safe, padded); + info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_DESC); + info("vendor: %x product: %x safe: %d padded: %d\n", + vendor, product, safe, padded); - // if we have vendor / product parameters patch them into id list + /* if we have vendor / product parameters patch them into id list */ if (vendor || product) { - info ("vendor: %x product: %x\n", vendor, product); + info("vendor: %x product: %x\n", vendor, product); for (i = 0; i < ARRAY_SIZE(id_table); i++) { if (!id_table[i].idVendor && !id_table[i].idProduct) { @@ -431,11 +457,11 @@ failed_usb_serial_register: return retval; } -static void __exit safe_exit (void) +static void __exit safe_exit(void) { - usb_deregister (&safe_driver); - usb_serial_deregister (&safe_device); + usb_deregister(&safe_driver); + usb_serial_deregister(&safe_device); } -module_init (safe_init); -module_exit (safe_exit); +module_init(safe_init); +module_exit(safe_exit); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 29074c1ba22b..2f6f1523ec56 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -250,7 +250,8 @@ struct sierra_port_private { int ri_state; }; -static int sierra_send_setup(struct usb_serial_port *port) +static int sierra_send_setup(struct tty_struct *tty, + struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; @@ -260,7 +261,7 @@ static int sierra_send_setup(struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - if (port->tty) { + if (tty) { int val = 0; if (portdata->dtr_state) val |= 0x01; @@ -284,32 +285,17 @@ static int sierra_send_setup(struct usb_serial_port *port) return 0; } -static void sierra_rx_throttle(struct usb_serial_port *port) +static void sierra_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s", __func__); + tty_termios_copy_hw(tty->termios, old_termios); + sierra_send_setup(tty, port); } -static void sierra_rx_unthrottle(struct usb_serial_port *port) -{ - dbg("%s", __func__); -} - -static void sierra_break_ctl(struct usb_serial_port *port, int break_state) -{ - /* Unfortunately, I don't know how to send a break */ - dbg("%s", __func__); -} - -static void sierra_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) -{ - dbg("%s", __func__); - tty_termios_copy_hw(port->tty->termios, old_termios); - sierra_send_setup(port); -} - -static int sierra_tiocmget(struct usb_serial_port *port, struct file *file) +static int sierra_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; unsigned int value; struct sierra_port_private *portdata; @@ -325,9 +311,10 @@ static int sierra_tiocmget(struct usb_serial_port *port, struct file *file) return value; } -static int sierra_tiocmset(struct usb_serial_port *port, struct file *file, +static int sierra_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct sierra_port_private *portdata; portdata = usb_get_serial_port_data(port); @@ -341,13 +328,7 @@ static int sierra_tiocmset(struct usb_serial_port *port, struct file *file, portdata->rts_state = 0; if (clear & TIOCM_DTR) portdata->dtr_state = 0; - return sierra_send_setup(port); -} - -static int sierra_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; + return sierra_send_setup(tty, port); } static void sierra_outdat_callback(struct urb *urb) @@ -374,8 +355,8 @@ static void sierra_outdat_callback(struct urb *urb) } /* Write */ -static int sierra_write(struct usb_serial_port *port, - const unsigned char *buf, int count) +static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { struct sierra_port_private *portdata = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; @@ -463,7 +444,7 @@ static void sierra_indat_callback(struct urb *urb) dbg("%s: nonzero status: %d on endpoint %02x.", __func__, status, endpoint); } else { - tty = port->tty; + tty = port->port.tty; if (urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); @@ -473,7 +454,7 @@ static void sierra_indat_callback(struct urb *urb) } /* Resubmit urb so we continue receiving */ - if (port->open_count && status != -ESHUTDOWN) { + if (port->port.count && status != -ESHUTDOWN) { err = usb_submit_urb(urb, GFP_ATOMIC); if (err) dev_err(&port->dev, "resubmit read urb failed." @@ -517,9 +498,9 @@ static void sierra_instat_callback(struct urb *urb) portdata->dsr_state = ((signals & 0x02) ? 1 : 0); portdata->ri_state = ((signals & 0x08) ? 1 : 0); - if (port->tty && !C_CLOCAL(port->tty) && + if (port->port.tty && !C_CLOCAL(port->port.tty) && old_dcd_state && !portdata->dcd_state) - tty_hangup(port->tty); + tty_hangup(port->port.tty); } else { dbg("%s: type %x req %x", __func__, req_pkt->bRequestType, req_pkt->bRequest); @@ -537,8 +518,9 @@ static void sierra_instat_callback(struct urb *urb) } } -static int sierra_write_room(struct usb_serial_port *port) +static int sierra_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct sierra_port_private *portdata = usb_get_serial_port_data(port); unsigned long flags; @@ -557,22 +539,8 @@ static int sierra_write_room(struct usb_serial_port *port) return 2048; } -static int sierra_chars_in_buffer(struct usb_serial_port *port) -{ - dbg("%s - port %d", __func__, port->number); - - /* - * We can't really account for how much data we - * have sent out, but hasn't made it through to the - * device as we can't see the backend here, so just - * tell the tty layer that everything is flushed. - * - * FIXME: should walk the outstanding urbs info - */ - return 0; -} - -static int sierra_open(struct usb_serial_port *port, struct file *filp) +static int sierra_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct sierra_port_private *portdata; struct usb_serial *serial = port->serial; @@ -612,9 +580,10 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) } } - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; - sierra_send_setup(port); + sierra_send_setup(tty, port); /* start up the interrupt endpoint if we have one */ if (port->interrupt_in_urb) { @@ -626,7 +595,8 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) return 0; } -static void sierra_close(struct usb_serial_port *port, struct file *filp) +static void sierra_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int i; struct usb_serial *serial = port->serial; @@ -641,7 +611,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp) if (serial->dev) { mutex_lock(&serial->disc_mutex); if (!serial->disconnected) - sierra_send_setup(port); + sierra_send_setup(tty, port); mutex_unlock(&serial->disc_mutex); /* Stop reading/writing urbs */ @@ -651,7 +621,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp) usb_kill_urb(port->interrupt_in_urb); - port->tty = NULL; + port->port.tty = NULL; /* FIXME */ } static int sierra_startup(struct usb_serial *serial) @@ -754,12 +724,7 @@ static struct usb_serial_driver sierra_device = { .close = sierra_close, .write = sierra_write, .write_room = sierra_write_room, - .chars_in_buffer = sierra_chars_in_buffer, - .throttle = sierra_rx_throttle, - .unthrottle = sierra_rx_unthrottle, - .ioctl = sierra_ioctl, .set_termios = sierra_set_termios, - .break_ctl = sierra_break_ctl, .tiocmget = sierra_tiocmget, .tiocmset = sierra_tiocmset, .attach = sierra_startup, @@ -792,7 +757,7 @@ failed_device_register: static void __exit sierra_exit(void) { - usb_deregister (&sierra_driver); + usb_deregister(&sierra_driver); usb_serial_deregister(&sierra_device); } diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 55b2570b8b8b..283cf6b36b2c 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -208,7 +208,7 @@ static inline unsigned int ringbuf_avail_data(struct ringbuf *pb) { if (pb == NULL) return 0; - return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); + return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size; } /* get the number of space in the pipo */ @@ -216,7 +216,7 @@ static inline unsigned int ringbuf_avail_space(struct ringbuf *pb) { if (pb == NULL) return 0; - return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); + return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size; } /* put count data into pipo */ @@ -448,7 +448,8 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value, /* close the serial port. We should wait for data sending to device 1st and * then kill all urb. */ -static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) +static void spcp8x5_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -464,7 +465,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) spin_lock_irqsave(&priv->lock, flags); timeout = SPCP8x5_CLOSING_WAIT; init_waitqueue_entry(&wait, current); - add_wait_queue(&port->tty->write_wait, &wait); + add_wait_queue(&tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (ringbuf_avail_data(priv->buf) == 0 || @@ -475,7 +476,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) spin_lock_irqsave(&priv->lock, flags); } set_current_state(TASK_RUNNING); - remove_wait_queue(&port->tty->write_wait, &wait); + remove_wait_queue(&tty->write_wait, &wait); /* clear out any remaining data in the buffer */ clear_ringbuf(priv->buf); @@ -486,7 +487,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) * flow control for data rates of 1200 bps or more, for lower rates we * should really know how much data is in the buffer to compute a delay * that is not unnecessarily long) */ - bps = tty_get_baud_rate(port->tty); + bps = tty_get_baud_rate(tty); if (bps > 1200) timeout = max((HZ*2560) / bps, HZ/10); else @@ -495,8 +496,8 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) schedule_timeout(timeout); /* clear control lines */ - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; + if (tty) { + c_cflag = tty->termios->c_cflag; if (c_cflag & HUPCL) { spin_lock_irqsave(&priv->lock, flags); priv->line_control = 0; @@ -518,14 +519,14 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) } /* set the serial param for transfer. we should check if we really need to - * transfer. then if be set flow contorl we should do this too. */ -static void spcp8x5_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) + * transfer. if we set flow control we should do this too. */ +static void spcp8x5_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; - unsigned int cflag = port->tty->termios->c_cflag; + unsigned int cflag = tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; unsigned short uartdata; unsigned char buf[2] = {0, 0}; @@ -533,21 +534,19 @@ static void spcp8x5_set_termios(struct usb_serial_port *port, int i; u8 control; - if ((!port->tty) || (!port->tty->termios)) - return; - /* for the 1st time call this function */ spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { - *(port->tty->termios) = tty_std_termios; - port->tty->termios->c_cflag = B115200 | CS8 | CREAD | - HUPCL | CLOCAL; + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; + tty->termios->c_ispeed = 115200; + tty->termios->c_ospeed = 115200; priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); /* check that they really want us to change something */ - if (!tty_termios_hw_change(port->tty->termios, old_termios)) + if (!tty_termios_hw_change(tty->termios, old_termios)) return; /* set DTR/RTS active */ @@ -567,7 +566,7 @@ static void spcp8x5_set_termios(struct usb_serial_port *port, } /* Set Baud Rate */ - baud = tty_get_baud_rate(port->tty);; + baud = tty_get_baud_rate(tty);; switch (baud) { case 300: buf[0] = 0x00; break; case 600: buf[0] = 0x01; break; @@ -643,7 +642,8 @@ static void spcp8x5_set_termios(struct usb_serial_port *port, /* open the serial port. do some usb system call. set termios and get the line * status of the device. then submit the read urb */ -static int spcp8x5_open(struct usb_serial_port *port, struct file *filp) +static int spcp8x5_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; @@ -665,7 +665,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp) return ret; spin_lock_irqsave(&priv->lock, flags); - if (port->tty->termios->c_cflag & CBAUD) + if (tty && (tty->termios->c_cflag & CBAUD)) priv->line_control = MCR_DTR | MCR_RTS; else priv->line_control = 0; @@ -674,8 +674,8 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp) spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); /* Setup termios */ - if (port->tty) - spcp8x5_set_termios(port, &tmp_termios); + if (tty) + spcp8x5_set_termios(tty, port, &tmp_termios); spcp8x5_get_msr(serial->dev, &status, priv->type); @@ -690,7 +690,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp) port->read_urb->dev = serial->dev; ret = usb_submit_urb(port->read_urb, GFP_KERNEL); if (ret) { - spcp8x5_close(port, NULL); + spcp8x5_close(tty, port, NULL); return -EPROTO; } return 0; @@ -717,7 +717,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) /* check the urb status */ if (urb->status) { - if (!port->open_count) + if (!port->port.count) return; if (urb->status == -EPROTO) { /* spcp8x5 mysteriously fails with -EPROTO */ @@ -755,7 +755,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) tty_flag = TTY_FRAME; dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ @@ -767,7 +767,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) } /* Schedule the next read _if_ we are still open */ - if (port->open_count) { + if (port->port.count) { urb->dev = port->serial->dev; result = usb_submit_urb(urb , GFP_ATOMIC); if (result) @@ -866,7 +866,7 @@ static void spcp8x5_write_bulk_callback(struct urb *urb) } /* write data to ring buffer. and then start the write transfer */ -static int spcp8x5_write(struct usb_serial_port *port, +static int spcp8x5_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); @@ -925,9 +925,10 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port, return 0; } -static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file, +static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); switch (cmd) { @@ -943,9 +944,10 @@ static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file, return -ENOIOCTLCMD; } -static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file, +static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 control; @@ -965,8 +967,9 @@ static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file, return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); } -static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file) +static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int mcr; @@ -989,8 +992,9 @@ static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file) } /* get the avail space room in ring buffer */ -static int spcp8x5_write_room(struct usb_serial_port *port) +static int spcp8x5_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct spcp8x5_private *priv = usb_get_serial_port_data(port); int room = 0; unsigned long flags; @@ -1003,8 +1007,9 @@ static int spcp8x5_write_room(struct usb_serial_port *port) } /* get the number of avail data in write ring buffer */ -static int spcp8x5_chars_in_buffer(struct usb_serial_port *port) +static int spcp8x5_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct spcp8x5_private *priv = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index a26a629dfc4f..e39c779e4160 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -16,7 +16,7 @@ * For questions or problems with this driver, contact Texas Instruments * technical support, or Al Borchers <alborchers@steinerpoint.com>, or * Peter Berger <pberger@brimson.com>. - * + * * This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052 * or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device * configuration. @@ -70,6 +70,7 @@ #include <linux/kernel.h> #include <linux/errno.h> +#include <linux/firmware.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/tty.h> @@ -81,7 +82,7 @@ #include <linux/serial.h> #include <linux/circ_buf.h> #include <linux/mutex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include <linux/firmware.h> @@ -149,21 +150,24 @@ struct ti_device { static int ti_startup(struct usb_serial *serial); static void ti_shutdown(struct usb_serial *serial); -static int ti_open(struct usb_serial_port *port, struct file *file); -static void ti_close(struct usb_serial_port *port, struct file *file); -static int ti_write(struct usb_serial_port *port, const unsigned char *data, - int count); -static int ti_write_room(struct usb_serial_port *port); -static int ti_chars_in_buffer(struct usb_serial_port *port); -static void ti_throttle(struct usb_serial_port *port); -static void ti_unthrottle(struct usb_serial_port *port); -static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); -static void ti_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios); -static int ti_tiocmget(struct usb_serial_port *port, struct file *file); -static int ti_tiocmset(struct usb_serial_port *port, struct file *file, - unsigned int set, unsigned int clear); -static void ti_break(struct usb_serial_port *port, int break_state); +static int ti_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *file); +static void ti_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *file); +static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *data, int count); +static int ti_write_room(struct tty_struct *tty); +static int ti_chars_in_buffer(struct tty_struct *tty); +static void ti_throttle(struct tty_struct *tty); +static void ti_unthrottle(struct tty_struct *tty); +static int ti_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void ti_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios); +static int ti_tiocmget(struct tty_struct *tty, struct file *file); +static int ti_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static void ti_break(struct tty_struct *tty, int break_state); static void ti_interrupt_callback(struct urb *urb); static void ti_bulk_in_callback(struct urb *urb); static void ti_bulk_out_callback(struct urb *urb); @@ -192,8 +196,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command, static int ti_write_byte(struct ti_device *tdev, unsigned long addr, __u8 mask, __u8 byte); -static int ti_download_firmware(struct ti_device *tdev, char *fw_name); - +static int ti_download_firmware(struct ti_device *tdev, int type); /* circular buffer */ static struct circ_buf *ti_buf_alloc(void); @@ -325,19 +328,25 @@ module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes"); module_param(low_latency, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(low_latency, "TTY low_latency flag, 0=off, 1=on, default is off"); +MODULE_PARM_DESC(low_latency, + "TTY low_latency flag, 0=off, 1=on, default is off"); module_param(closing_wait, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000"); +MODULE_PARM_DESC(closing_wait, + "Maximum wait for data to drain in close, in .01 secs, default is 4000"); module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO); -MODULE_PARM_DESC(vendor_3410, "Vendor ids for 3410 based devices, 1-5 short integers"); +MODULE_PARM_DESC(vendor_3410, + "Vendor ids for 3410 based devices, 1-5 short integers"); module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO); -MODULE_PARM_DESC(product_3410, "Product ids for 3410 based devices, 1-5 short integers"); +MODULE_PARM_DESC(product_3410, + "Product ids for 3410 based devices, 1-5 short integers"); module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO); -MODULE_PARM_DESC(vendor_5052, "Vendor ids for 5052 based devices, 1-5 short integers"); +MODULE_PARM_DESC(vendor_5052, + "Vendor ids for 5052 based devices, 1-5 short integers"); module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO); -MODULE_PARM_DESC(product_5052, "Product ids for 5052 based devices, 1-5 short integers"); +MODULE_PARM_DESC(product_5052, + "Product ids for 5052 based devices, 1-5 short integers"); MODULE_DEVICE_TABLE(usb, ti_id_table_combined); @@ -346,18 +355,18 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined); static int __init ti_init(void) { - int i,j; + int i, j; int ret; /* insert extra vendor and product ids */ j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1; - for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) { + for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++) { ti_id_table_3410[j].idVendor = vendor_3410[i]; ti_id_table_3410[j].idProduct = product_3410[i]; ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE; } j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1; - for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) { + for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++) { ti_id_table_5052[j].idVendor = vendor_5052[i]; ti_id_table_5052[j].idProduct = product_5052[i]; ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE; @@ -426,15 +435,15 @@ static int ti_startup(struct usb_serial *serial) /* determine device type */ if (usb_match_id(serial->interface, ti_id_table_3410)) tdev->td_is_3410 = 1; - dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052"); + dbg("%s - device type is %s", __func__, + tdev->td_is_3410 ? "3410" : "5052"); /* if we have only 1 configuration, download firmware */ if (dev->descriptor.bNumConfigurations == 1) { - if (tdev->td_is_3410) - status = ti_download_firmware(tdev, "ti_3410.fw"); + status = ti_download_firmware(tdev, 3410); else - status = ti_download_firmware(tdev, "ti_5052.fw"); + status = ti_download_firmware(tdev, 5052); if (status) goto free_tdev; @@ -446,7 +455,7 @@ static int ti_startup(struct usb_serial *serial) status = -ENODEV; goto free_tdev; - } + } /* the second configuration must be set (in sysfs by hotplug script) */ if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) { @@ -463,7 +472,8 @@ static int ti_startup(struct usb_serial *serial) goto free_tports; } spin_lock_init(&tport->tp_lock); - tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); + tport->tp_uart_base_addr = (i == 0 ? + TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0; tport->tp_closing_wait = closing_wait; init_waitqueue_head(&tport->tp_msr_wait); @@ -480,11 +490,11 @@ static int ti_startup(struct usb_serial *serial) usb_set_serial_port_data(serial->port[i], tport); tport->tp_uart_mode = 0; /* default is RS232 */ } - + return 0; free_tports: - for (--i; i>=0; --i) { + for (--i; i >= 0; --i) { tport = usb_get_serial_port_data(serial->port[i]); ti_buf_free(tport->tp_write_buf); kfree(tport); @@ -505,7 +515,7 @@ static void ti_shutdown(struct usb_serial *serial) dbg("%s", __func__); - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) { tport = usb_get_serial_port_data(serial->port[i]); if (tport) { ti_buf_free(tport->tp_write_buf); @@ -519,7 +529,8 @@ static void ti_shutdown(struct usb_serial *serial) } -static int ti_open(struct usb_serial_port *port, struct file *file) +static int ti_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *file) { struct ti_port *tport = usb_get_serial_port_data(port); struct ti_device *tdev; @@ -527,8 +538,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file) struct urb *urb; int port_number; int status; - __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS | - TI_PIPE_TIMEOUT_ENABLE | + __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS | + TI_PIPE_TIMEOUT_ENABLE | (TI_TRANSFER_TIMEOUT << 2)); dbg("%s - port %d", __func__, port->number); @@ -543,9 +554,9 @@ static int ti_open(struct usb_serial_port *port, struct file *file) if (mutex_lock_interruptible(&tdev->td_open_close_lock)) return -ERESTARTSYS; - if (port->tty) - port->tty->low_latency = - (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; + if (tty) + tty->low_latency = + (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; port_number = port->number - port->serial->minor; @@ -559,7 +570,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file) dbg("%s - start interrupt in urb", __func__); urb = tdev->td_serial->port[0]->interrupt_in_urb; if (!urb) { - dev_err(&port->dev, "%s - no interrupt urb\n", __func__); + dev_err(&port->dev, "%s - no interrupt urb\n", + __func__); status = -EINVAL; goto release_lock; } @@ -568,18 +580,22 @@ static int ti_open(struct usb_serial_port *port, struct file *file) urb->dev = dev; status = usb_submit_urb(urb, GFP_KERNEL); if (status) { - dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status); + dev_err(&port->dev, + "%s - submit interrupt urb failed, %d\n", + __func__, status); goto release_lock; } } - ti_set_termios(port, port->tty->termios); + if (tty) + ti_set_termios(tty, port, tty->termios); dbg("%s - sending TI_OPEN_PORT", __func__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { - dev_err(&port->dev, "%s - cannot send open command, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot send open command, %d\n", + __func__, status); goto unlink_int_urb; } @@ -587,7 +603,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file) status = ti_command_out_sync(tdev, TI_START_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) { - dev_err(&port->dev, "%s - cannot send start command, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot send start command, %d\n", + __func__, status); goto unlink_int_urb; } @@ -595,13 +612,15 @@ static int ti_open(struct usb_serial_port *port, struct file *file) status = ti_command_out_sync(tdev, TI_PURGE_PORT, (__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0); if (status) { - dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", + __func__, status); goto unlink_int_urb; } status = ti_command_out_sync(tdev, TI_PURGE_PORT, (__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0); if (status) { - dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", + __func__, status); goto unlink_int_urb; } @@ -610,13 +629,15 @@ static int ti_open(struct usb_serial_port *port, struct file *file) usb_clear_halt(dev, port->write_urb->pipe); usb_clear_halt(dev, port->read_urb->pipe); - ti_set_termios(port, port->tty->termios); + if (tty) + ti_set_termios(tty, port, tty->termios); dbg("%s - sending TI_OPEN_PORT (2)", __func__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { - dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot send open command (2), %d\n", + __func__, status); goto unlink_int_urb; } @@ -624,7 +645,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file) status = ti_command_out_sync(tdev, TI_START_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) { - dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot send start command (2), %d\n", + __func__, status); goto unlink_int_urb; } @@ -642,7 +664,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file) urb->dev = dev; status = usb_submit_urb(urb, GFP_KERNEL); if (status) { - dev_err(&port->dev, "%s - submit read urb failed, %d\n", __func__, status); + dev_err(&port->dev, "%s - submit read urb failed, %d\n", + __func__, status); goto unlink_int_urb; } @@ -661,7 +684,8 @@ release_lock: } -static void ti_close(struct usb_serial_port *port, struct file *file) +static void ti_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *file) { struct ti_device *tdev; struct ti_port *tport; @@ -670,7 +694,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file) int do_unlock; dbg("%s - port %d", __func__, port->number); - + tdev = usb_get_serial_data(port->serial); tport = usb_get_serial_port_data(port); if (tdev == NULL || tport == NULL) @@ -690,7 +714,9 @@ static void ti_close(struct usb_serial_port *port, struct file *file) status = ti_command_out_sync(tdev, TI_CLOSE_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) - dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __func__, status); + dev_err(&port->dev, + "%s - cannot send close port command, %d\n" + , __func__, status); /* if mutex_lock is interrupted, continue anyway */ do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock); @@ -707,8 +733,8 @@ static void ti_close(struct usb_serial_port *port, struct file *file) } -static int ti_write(struct usb_serial_port *port, const unsigned char *data, - int count) +static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *data, int count) { struct ti_port *tport = usb_get_serial_port_data(port); unsigned long flags; @@ -733,8 +759,9 @@ static int ti_write(struct usb_serial_port *port, const unsigned char *data, } -static int ti_write_room(struct usb_serial_port *port) +static int ti_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); int room = 0; unsigned long flags; @@ -743,7 +770,7 @@ static int ti_write_room(struct usb_serial_port *port) if (tport == NULL) return -ENODEV; - + spin_lock_irqsave(&tport->tp_lock, flags); room = ti_buf_space_avail(tport->tp_write_buf); spin_unlock_irqrestore(&tport->tp_lock, flags); @@ -753,8 +780,9 @@ static int ti_write_room(struct usb_serial_port *port) } -static int ti_chars_in_buffer(struct usb_serial_port *port) +static int ti_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; @@ -773,32 +801,26 @@ static int ti_chars_in_buffer(struct usb_serial_port *port) } -static void ti_throttle(struct usb_serial_port *port) +static void ti_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - struct tty_struct *tty; dbg("%s - port %d", __func__, port->number); if (tport == NULL) return; - tty = port->tty; - if (!tty) { - dbg("%s - no tty", __func__); - return; - } - if (I_IXOFF(tty) || C_CRTSCTS(tty)) ti_stop_read(tport, tty); } -static void ti_unthrottle(struct usb_serial_port *port) +static void ti_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - struct tty_struct *tty; int status; dbg("%s - port %d", __func__, port->number); @@ -806,23 +828,19 @@ static void ti_unthrottle(struct usb_serial_port *port) if (tport == NULL) return; - tty = port->tty; - if (!tty) { - dbg("%s - no tty", __func__); - return; - } - if (I_IXOFF(tty) || C_CRTSCTS(tty)) { status = ti_restart_read(tport, tty); if (status) - dev_err(&port->dev, "%s - cannot restart read, %d\n", __func__, status); + dev_err(&port->dev, "%s - cannot restart read, %d\n", + __func__, status); } } -static int ti_ioctl(struct usb_serial_port *port, struct file *file, +static int ti_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); struct async_icount cnow; struct async_icount cprev; @@ -833,55 +851,52 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file, return -ENODEV; switch (cmd) { - case TIOCGSERIAL: - dbg("%s - (%d) TIOCGSERIAL", __func__, port->number); - return ti_get_serial_info(tport, (struct serial_struct __user *)arg); - break; - - case TIOCSSERIAL: - dbg("%s - (%d) TIOCSSERIAL", __func__, port->number); - return ti_set_serial_info(tport, (struct serial_struct __user *)arg); - break; - - case TIOCMIWAIT: - dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); - cprev = tport->tp_icount; - while (1) { - interruptible_sleep_on(&tport->tp_msr_wait); - if (signal_pending(current)) - return -ERESTARTSYS; - cnow = tport->tp_icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; - } - break; - - case TIOCGICOUNT: - dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, tport->tp_icount.rx, tport->tp_icount.tx); - if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount))) - return -EFAULT; - return 0; + case TIOCGSERIAL: + dbg("%s - (%d) TIOCGSERIAL", __func__, port->number); + return ti_get_serial_info(tport, + (struct serial_struct __user *)arg); + case TIOCSSERIAL: + dbg("%s - (%d) TIOCSSERIAL", __func__, port->number); + return ti_set_serial_info(tport, + (struct serial_struct __user *)arg); + case TIOCMIWAIT: + dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); + cprev = tport->tp_icount; + while (1) { + interruptible_sleep_on(&tport->tp_msr_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + cnow = tport->tp_icount; + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) + return 0; + cprev = cnow; + } + break; + case TIOCGICOUNT: + dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", + __func__, port->number, + tport->tp_icount.rx, tport->tp_icount.tx); + if (copy_to_user((void __user *)arg, &tport->tp_icount, + sizeof(tport->tp_icount))) + return -EFAULT; + return 0; } - return -ENOIOCTLCMD; } -static void ti_set_termios(struct usb_serial_port *port, - struct ktermios *old_termios) +static void ti_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct ti_port *tport = usb_get_serial_port_data(port); - struct tty_struct *tty = port->tty; struct ti_uart_config *config; - tcflag_t cflag,iflag; + tcflag_t cflag, iflag; int baud; int status; int port_number = port->number - port->serial->minor; @@ -893,7 +908,8 @@ static void ti_set_termios(struct usb_serial_port *port, iflag = tty->termios->c_iflag; dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag); - dbg("%s - old clfag %08x, old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag); + dbg("%s - old clfag %08x, old iflag %08x", __func__, + old_termios->c_cflag, old_termios->c_iflag); if (tport == NULL) return; @@ -912,19 +928,19 @@ static void ti_set_termios(struct usb_serial_port *port, config->bUartMode = (__u8)(tport->tp_uart_mode); switch (cflag & CSIZE) { - case CS5: - config->bDataBits = TI_UART_5_DATA_BITS; - break; - case CS6: - config->bDataBits = TI_UART_6_DATA_BITS; - break; - case CS7: - config->bDataBits = TI_UART_7_DATA_BITS; - break; - default: - case CS8: - config->bDataBits = TI_UART_8_DATA_BITS; - break; + case CS5: + config->bDataBits = TI_UART_5_DATA_BITS; + break; + case CS6: + config->bDataBits = TI_UART_6_DATA_BITS; + break; + case CS7: + config->bDataBits = TI_UART_7_DATA_BITS; + break; + default: + case CS8: + config->bDataBits = TI_UART_8_DATA_BITS; + break; } /* CMSPAR isn't supported by this driver */ @@ -940,7 +956,7 @@ static void ti_set_termios(struct usb_serial_port *port, } } else { config->wFlags &= ~TI_UART_ENABLE_PARITY_CHECKING; - config->bParity = TI_UART_NO_PARITY; + config->bParity = TI_UART_NO_PARITY; } if (cflag & CSTOPB) @@ -993,7 +1009,8 @@ static void ti_set_termios(struct usb_serial_port *port, (__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config, sizeof(*config)); if (status) - dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __func__, port_number, status); + dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", + __func__, port_number, status); /* SET_CONFIG asserts RTS and DTR, reset them correctly */ mcr = tport->tp_shadow_mcr; @@ -1002,14 +1019,17 @@ static void ti_set_termios(struct usb_serial_port *port, mcr &= ~(TI_MCR_DTR | TI_MCR_RTS); status = ti_set_mcr(tport, mcr); if (status) - dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __func__, port_number, status); + dev_err(&port->dev, + "%s - cannot set modem control on port %d, %d\n", + __func__, port_number, status); kfree(config); } -static int ti_tiocmget(struct usb_serial_port *port, struct file *file) +static int ti_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); unsigned int result; unsigned int msr; @@ -1040,9 +1060,10 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file) } -static int ti_tiocmset(struct usb_serial_port *port, struct file *file, +static int ti_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); unsigned int mcr; unsigned long flags; @@ -1074,8 +1095,9 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file, } -static void ti_break(struct usb_serial_port *port, int break_state) +static void ti_break(struct tty_struct *tty, int break_state) { + struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); int status; @@ -1141,10 +1163,12 @@ static void ti_interrupt_callback(struct urb *urb) port_number = TI_GET_PORT_FROM_CODE(data[0]); function = TI_GET_FUNC_FROM_CODE(data[0]); - dbg("%s - port_number %d, function %d, data 0x%02X", __func__, port_number, function, data[1]); + dbg("%s - port_number %d, function %d, data 0x%02X", + __func__, port_number, function, data[1]); if (port_number >= serial->num_ports) { - dev_err(dev, "%s - bad port number, %d\n", __func__, port_number); + dev_err(dev, "%s - bad port number, %d\n", + __func__, port_number); goto exit; } @@ -1156,7 +1180,8 @@ static void ti_interrupt_callback(struct urb *urb) switch (function) { case TI_CODE_DATA_ERROR: - dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __func__, port_number, data[1]); + dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", + __func__, port_number, data[1]); break; case TI_CODE_MODEM_STATUS: @@ -1166,7 +1191,8 @@ static void ti_interrupt_callback(struct urb *urb) break; default: - dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __func__, data[1]); + dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", + __func__, data[1]); break; } @@ -1200,7 +1226,7 @@ static void ti_bulk_in_callback(struct urb *urb) return; default: dev_err(dev, "%s - nonzero urb status, %d\n", - __func__, status ); + __func__, status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); } @@ -1213,15 +1239,16 @@ static void ti_bulk_in_callback(struct urb *urb) return; } - if (port->tty && urb->actual_length) { + if (port->port.tty && urb->actual_length) { usb_serial_debug_data(debug, dev, __func__, urb->actual_length, urb->transfer_buffer); if (!tport->tp_is_open) dbg("%s - port closed, dropping data", __func__); else - ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer, - urb->actual_length); + ti_recv(&urb->dev->dev, port->port.tty, + urb->transfer_buffer, + urb->actual_length); spin_lock(&tport->tp_lock); tport->tp_icount.rx += urb->actual_length; @@ -1285,8 +1312,9 @@ static void ti_recv(struct device *dev, struct tty_struct *tty, do { cnt = tty_buffer_request_room(tty, length); if (cnt < length) { - dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt); - if(cnt == 0) + dev_err(dev, "%s - dropping data, %d bytes lost\n", + __func__, length - cnt); + if (cnt == 0) break; } tty_insert_flip_string(tty, data, cnt); @@ -1302,7 +1330,7 @@ static void ti_send(struct ti_port *tport) { int count, result; struct usb_serial_port *port = tport->tp_port; - struct tty_struct *tty = port->tty; + struct tty_struct *tty = port->port.tty; /* FIXME */ unsigned long flags; @@ -1328,7 +1356,8 @@ static void ti_send(struct ti_port *tport) spin_unlock_irqrestore(&tport->tp_lock, flags); - usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer); + usb_serial_debug_data(debug, &port->dev, __func__, count, + port->write_urb->transfer_buffer); usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, @@ -1338,8 +1367,9 @@ static void ti_send(struct ti_port *tport) result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - submit write urb failed, %d\n", __func__, result); - tport->tp_write_urb_in_use = 0; + dev_err(&port->dev, "%s - submit write urb failed, %d\n", + __func__, result); + tport->tp_write_urb_in_use = 0; /* TODO: reschedule ti_send */ } else { spin_lock_irqsave(&tport->tp_lock, flags); @@ -1374,7 +1404,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr) static int ti_get_lsr(struct ti_port *tport) { - int size,status; + int size, status; struct ti_device *tdev = tport->tp_tdev; struct usb_serial_port *port = tport->tp_port; int port_number = port->number - port->serial->minor; @@ -1392,7 +1422,9 @@ static int ti_get_lsr(struct ti_port *tport) status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS, (__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size); if (status) { - dev_err(&port->dev, "%s - get port status command failed, %d\n", __func__, status); + dev_err(&port->dev, + "%s - get port status command failed, %d\n", + __func__, status); goto free_data; } @@ -1442,8 +1474,9 @@ static int ti_set_serial_info(struct ti_port *tport, return -EFAULT; tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; - if (port->tty) - port->tty->low_latency = + /* FIXME */ + if (port->port.tty) + port->port.tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; tport->tp_closing_wait = new_serial.closing_wait; @@ -1477,7 +1510,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) tport->tp_msr = msr & TI_MSR_MASK; /* handle CTS flow control */ - tty = tport->tp_port->tty; + tty = tport->tp_port->port.tty; if (tty && C_CRTSCTS(tty)) { if (msr & TI_MSR_CTS) { tty->hw_stopped = 0; @@ -1627,7 +1660,8 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr, struct ti_write_data_bytes *data; struct device *dev = &tdev->td_serial->dev->dev; - dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __func__, addr, mask, byte); + dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", + __func__, addr, mask, byte); size = sizeof(struct ti_write_data_bytes) + 2; data = kmalloc(size, GFP_KERNEL); @@ -1655,67 +1689,68 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr, return status; } - -static int ti_download_firmware(struct ti_device *tdev, - char *fw_name) +static int ti_do_download(struct usb_device *dev, int pipe, + u8 *buffer, int size) { - const struct firmware *fw; - int status = 0; - int buffer_size; int pos; - int len; + u8 cs = 0; int done; - __u8 cs = 0; - __u8 *buffer; - struct usb_device *dev = tdev->td_serial->dev; struct ti_firmware_header *header; - unsigned int pipe = usb_sndbulkpipe(dev, - tdev->td_serial->port[0]->bulk_out_endpointAddress); - - buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header); - - if (request_firmware(&fw, fw_name, &dev->dev)) { - dev_err(&dev->dev, "%s - failed to load firmware \"%s\"\n", - __func__, fw_name); - return -ENOENT; - } - if (fw->size > buffer_size) { - dev_err(&dev->dev, "%s - firmware \"%s\" is too large\n", - __func__, fw_name); - release_firmware(fw); - return -EINVAL; - } - - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - release_firmware(fw); - return -ENOMEM; - } - - memcpy(buffer, fw->data, fw->size); - memset(buffer+fw->size, 0xff, buffer_size-fw->size); + int status; + int len; - for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++) + for (pos = sizeof(struct ti_firmware_header); pos < size; pos++) cs = (__u8)(cs + buffer[pos]); header = (struct ti_firmware_header *)buffer; - header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header))); + header->wLength = cpu_to_le16((__u16)(size + - sizeof(struct ti_firmware_header))); header->bCheckSum = cs; dbg("%s - downloading firmware", __func__); - for (pos = 0; pos < buffer_size; pos += done) { - len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE); - status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000); + for (pos = 0; pos < size; pos += done) { + len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE); + status = usb_bulk_msg(dev, pipe, buffer + pos, len, + &done, 1000); if (status) break; } + return status; +} - kfree(buffer); - release_firmware(fw); +static int ti_download_firmware(struct ti_device *tdev, int type) +{ + int status = -ENOMEM; + int buffer_size; + __u8 *buffer; + struct usb_device *dev = tdev->td_serial->dev; + unsigned int pipe = usb_sndbulkpipe(dev, + tdev->td_serial->port[0]->bulk_out_endpointAddress); + const struct firmware *fw_p; + char buf[32]; + sprintf(buf, "ti_usb-%d.bin", type); + if (request_firmware(&fw_p, buf, &dev->dev)) { + dev_err(&dev->dev, "%s - firmware not found\n", __func__); + return -ENOENT; + } + if (fw_p->size > TI_FIRMWARE_BUF_SIZE) { + dev_err(&dev->dev, "%s - firmware too large\n", __func__); + return -ENOENT; + } + + buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header); + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer) { + memcpy(buffer, fw_p->data, fw_p->size); + memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size); + ti_do_download(dev, pipe, buffer, fw_p->size); + kfree(buffer); + } + release_firmware(fw_p); if (status) { - dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status); + dev_err(&dev->dev, "%s - error downloading firmware, %d\n", + __func__, status); return status; } @@ -1787,7 +1822,7 @@ static void ti_buf_clear(struct circ_buf *cb) static int ti_buf_data_avail(struct circ_buf *cb) { - return CIRC_CNT(cb->head,cb->tail,TI_WRITE_BUF_SIZE); + return CIRC_CNT(cb->head, cb->tail, TI_WRITE_BUF_SIZE); } @@ -1800,7 +1835,7 @@ static int ti_buf_data_avail(struct circ_buf *cb) static int ti_buf_space_avail(struct circ_buf *cb) { - return CIRC_SPACE(cb->head,cb->tail,TI_WRITE_BUF_SIZE); + return CIRC_SPACE(cb->head, cb->tail, TI_WRITE_BUF_SIZE); } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 0cb0d77dc429..8c2d531eedea 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -12,7 +12,8 @@ * This driver was originally based on the ACM driver by Armin Fuerst (which was * based on a driver by Brad Keryan) * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * */ @@ -28,7 +29,7 @@ #include <linux/spinlock.h> #include <linux/mutex.h> #include <linux/list.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "pl2303.h" @@ -59,7 +60,8 @@ static struct usb_driver usb_serial_driver = { */ static int debug; -static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ +/* initially all NULL */ +static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; static DEFINE_MUTEX(table_lock); static LIST_HEAD(usb_serial_driver_list); @@ -76,7 +78,8 @@ struct usb_serial *usb_serial_get_by_index(unsigned index) return serial; } -static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_ports, unsigned int *minor) +static struct usb_serial *get_free_serial(struct usb_serial *serial, + int num_ports, unsigned int *minor) { unsigned int i, j; int good_spot; @@ -122,9 +125,8 @@ static void return_serial(struct usb_serial *serial) if (serial == NULL) return; - for (i = 0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) serial_table[serial->minor + i] = NULL; - } } static void destroy_serial(struct kref *kref) @@ -143,7 +145,7 @@ static void destroy_serial(struct kref *kref) return_serial(serial); for (i = 0; i < serial->num_ports; ++i) - serial->port[i]->open_count = 0; + serial->port[i]->port.count = 0; /* the ports are cleaned up and released in port_release() */ for (i = 0; i < serial->num_ports; ++i) @@ -156,7 +158,8 @@ static void destroy_serial(struct kref *kref) * not get cleaned up in port_release() as it was never registered with * the driver core */ if (serial->num_ports < serial->num_port_pointers) { - for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { + for (i = serial->num_ports; + i < serial->num_port_pointers; ++i) { port = serial->port[i]; if (!port) continue; @@ -167,7 +170,7 @@ static void destroy_serial(struct kref *kref) usb_put_dev(serial->dev); /* free up any memory that we allocated */ - kfree (serial); + kfree(serial); } void usb_serial_put(struct usb_serial *serial) @@ -180,13 +183,13 @@ void usb_serial_put(struct usb_serial *serial) /***************************************************************************** * Driver tty interface functions *****************************************************************************/ -static int serial_open (struct tty_struct *tty, struct file * filp) +static int serial_open (struct tty_struct *tty, struct file *filp) { struct usb_serial *serial; struct usb_serial_port *port; unsigned int portNumber; int retval; - + dbg("%s", __func__); /* get the serial object associated with this tty pointer */ @@ -207,15 +210,15 @@ static int serial_open (struct tty_struct *tty, struct file * filp) retval = -ERESTARTSYS; goto bailout_kref_put; } - - ++port->open_count; + + ++port->port.count; /* set up our port structure making the tty driver * remember our port object, and us it */ tty->driver_data = port; - port->tty = tty; + port->port.tty = tty; - if (port->open_count == 1) { + if (port->port.count == 1) { /* lock this module before we call it * this may fail, which means we must bail out, @@ -228,9 +231,9 @@ static int serial_open (struct tty_struct *tty, struct file * filp) retval = usb_autopm_get_interface(serial->interface); if (retval) goto bailout_module_put; - /* only call the device specific open if this + /* only call the device specific open if this * is the first time the port is opened */ - retval = serial->type->open(port, filp); + retval = serial->type->open(tty, port, filp); if (retval) goto bailout_interface_put; } @@ -243,16 +246,16 @@ bailout_interface_put: bailout_module_put: module_put(serial->type->driver.owner); bailout_mutex_unlock: - port->open_count = 0; + port->port.count = 0; tty->driver_data = NULL; - port->tty = NULL; + port->port.tty = NULL; mutex_unlock(&port->mutex); bailout_kref_put: usb_serial_put(serial); return retval; } -static void serial_close(struct tty_struct *tty, struct file * filp) +static void serial_close(struct tty_struct *tty, struct file *filp) { struct usb_serial_port *port = tty->driver_data; @@ -263,27 +266,30 @@ static void serial_close(struct tty_struct *tty, struct file * filp) mutex_lock(&port->mutex); - if (port->open_count == 0) { + if (port->port.count == 0) { mutex_unlock(&port->mutex); return; } - --port->open_count; - if (port->open_count == 0) - /* only call the device specific close if this + --port->port.count; + if (port->port.count == 0) + /* only call the device specific close if this * port is being closed by the last owner */ - port->serial->type->close(port, filp); + port->serial->type->close(tty, port, filp); - if (port->open_count == (port->console? 1 : 0)) { - if (port->tty) { - if (port->tty->driver_data) - port->tty->driver_data = NULL; - port->tty = NULL; + if (port->port.count == (port->console? 1 : 0)) { + if (port->port.tty) { + if (port->port.tty->driver_data) + port->port.tty->driver_data = NULL; + port->port.tty = NULL; } } - if (port->open_count == 0) { - usb_autopm_put_interface(port->serial->interface); + if (port->port.count == 0) { + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) + usb_autopm_put_interface(port->serial->interface); + mutex_unlock(&port->serial->disc_mutex); module_put(port->serial->type->driver.owner); } @@ -291,7 +297,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp) usb_serial_put(port->serial); } -static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) +static int serial_write(struct tty_struct *tty, const unsigned char *buf, + int count) { struct usb_serial_port *port = tty->driver_data; int retval = -ENODEV; @@ -301,107 +308,112 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int dbg("%s - port %d, %d byte(s)", __func__, port->number, count); - /* open_count is managed under the mutex lock for the tty so cannot - drop to zero until after the last close completes */ - WARN_ON(!port->open_count); + /* count is managed under the mutex lock for the tty so cannot + drop to zero until after the last close completes */ + WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ - retval = port->serial->type->write(port, buf, count); + retval = port->serial->type->write(tty, port, buf, count); exit: return retval; } -static int serial_write_room (struct tty_struct *tty) +static int serial_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->open_count); + WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ - return port->serial->type->write_room(port); + return port->serial->type->write_room(tty); } -static int serial_chars_in_buffer (struct tty_struct *tty) +static int serial_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; dbg("%s = port %d", __func__, port->number); - WARN_ON(!port->open_count); + WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ - return port->serial->type->chars_in_buffer(port); + return port->serial->type->chars_in_buffer(tty); } -static void serial_throttle (struct tty_struct * tty) +static void serial_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->open_count); + WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ if (port->serial->type->throttle) - port->serial->type->throttle(port); + port->serial->type->throttle(tty); } -static void serial_unthrottle (struct tty_struct * tty) +static void serial_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->open_count); + WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ if (port->serial->type->unthrottle) - port->serial->type->unthrottle(port); + port->serial->type->unthrottle(tty); } -static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) +static int serial_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; int retval = -ENODEV; dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); - WARN_ON(!port->open_count); + WARN_ON(!port->port.count); - /* pass on to the driver specific version of this function if it is available */ + /* pass on to the driver specific version of this function + if it is available */ if (port->serial->type->ioctl) { lock_kernel(); - retval = port->serial->type->ioctl(port, file, cmd, arg); + retval = port->serial->type->ioctl(tty, file, cmd, arg); unlock_kernel(); - } - else + } else retval = -ENOIOCTLCMD; return retval; } -static void serial_set_termios (struct tty_struct *tty, struct ktermios * old) +static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->open_count); - /* pass on to the driver specific version of this function if it is available */ + WARN_ON(!port->port.count); + /* pass on to the driver specific version of this function + if it is available */ if (port->serial->type->set_termios) - port->serial->type->set_termios(port, old); + port->serial->type->set_termios(tty, port, old); else tty_termios_copy_hw(tty->termios, old); } -static void serial_break (struct tty_struct *tty, int break_state) +static int serial_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->open_count); - /* pass on to the driver specific version of this function if it is available */ + WARN_ON(!port->port.count); + /* pass on to the driver specific version of this function + if it is available */ if (port->serial->type->break_ctl) { lock_kernel(); - port->serial->type->break_ctl(port, break_state); + port->serial->type->break_ctl(tty, break_state); unlock_kernel(); } + return 0; } -static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) +static int serial_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) { struct usb_serial *serial; int length = 0; @@ -410,26 +422,29 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int char tmp[40]; dbg("%s", __func__); - length += sprintf (page, "usbserinfo:1.0 driver:2.0\n"); + length += sprintf(page, "usbserinfo:1.0 driver:2.0\n"); for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) { serial = usb_serial_get_by_index(i); if (serial == NULL) continue; - length += sprintf (page+length, "%d:", i); + length += sprintf(page+length, "%d:", i); if (serial->type->driver.owner) - length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner)); - length += sprintf (page+length, " name:\"%s\"", serial->type->description); - length += sprintf (page+length, " vendor:%04x product:%04x", - le16_to_cpu(serial->dev->descriptor.idVendor), - le16_to_cpu(serial->dev->descriptor.idProduct)); - length += sprintf (page+length, " num_ports:%d", serial->num_ports); - length += sprintf (page+length, " port:%d", i - serial->minor + 1); - + length += sprintf(page+length, " module:%s", + module_name(serial->type->driver.owner)); + length += sprintf(page+length, " name:\"%s\"", + serial->type->description); + length += sprintf(page+length, " vendor:%04x product:%04x", + le16_to_cpu(serial->dev->descriptor.idVendor), + le16_to_cpu(serial->dev->descriptor.idProduct)); + length += sprintf(page+length, " num_ports:%d", + serial->num_ports); + length += sprintf(page+length, " port:%d", + i - serial->minor + 1); usb_make_path(serial->dev, tmp, sizeof(tmp)); - length += sprintf (page+length, " path:%s", tmp); - - length += sprintf (page+length, "\n"); + length += sprintf(page+length, " path:%s", tmp); + + length += sprintf(page+length, "\n"); if ((length + begin) > (off + count)) { usb_serial_put(serial); goto done; @@ -445,31 +460,31 @@ done: if (off >= (length + begin)) return 0; *start = page + (off-begin); - return ((count < begin+length-off) ? count : begin+length-off); + return (count < begin+length-off) ? count : begin+length-off; } -static int serial_tiocmget (struct tty_struct *tty, struct file *file) +static int serial_tiocmget(struct tty_struct *tty, struct file *file) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->open_count); + WARN_ON(!port->port.count); if (port->serial->type->tiocmget) - return port->serial->type->tiocmget(port, file); + return port->serial->type->tiocmget(tty, file); return -EINVAL; } -static int serial_tiocmset (struct tty_struct *tty, struct file *file, +static int serial_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->open_count); + WARN_ON(!port->port.count); if (port->serial->type->tiocmset) - return port->serial->type->tiocmset(port, file, set, clear); + return port->serial->type->tiocmset(tty, file, set, clear); return -EINVAL; } @@ -482,6 +497,7 @@ void usb_serial_port_softint(struct usb_serial_port *port) { schedule_work(&port->work); } +EXPORT_SYMBOL_GPL(usb_serial_port_softint); static void usb_serial_port_work(struct work_struct *work) { @@ -490,11 +506,11 @@ static void usb_serial_port_work(struct work_struct *work) struct tty_struct *tty; dbg("%s - port %d", __func__, port->number); - + if (!port) return; - tty = port->tty; + tty = port->port.tty; if (!tty) return; @@ -505,7 +521,7 @@ static void port_release(struct device *dev) { struct usb_serial_port *port = to_usb_serial_port(dev); - dbg ("%s - %s", __func__, dev->bus_id); + dbg ("%s - %s", __func__, dev_name(dev)); port_free(port); } @@ -543,9 +559,9 @@ static void port_free(struct usb_serial_port *port) kfree(port); } -static struct usb_serial * create_serial (struct usb_device *dev, - struct usb_interface *interface, - struct usb_serial_driver *driver) +static struct usb_serial *create_serial(struct usb_device *dev, + struct usb_interface *interface, + struct usb_serial_driver *driver) { struct usb_serial *serial; @@ -564,7 +580,7 @@ static struct usb_serial * create_serial (struct usb_device *dev, } static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf, - struct usb_serial_driver *drv) + struct usb_serial_driver *drv) { struct usb_dynid *dynid; @@ -596,7 +612,8 @@ exit: return id; } -static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) +static struct usb_serial_driver *search_serial_device( + struct usb_interface *iface) { const struct usb_device_id *id; struct usb_serial_driver *drv; @@ -614,7 +631,7 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac int usb_serial_probe(struct usb_interface *interface, const struct usb_device_id *id) { - struct usb_device *dev = interface_to_usbdev (interface); + struct usb_device *dev = interface_to_usbdev(interface); struct usb_serial *serial = NULL; struct usb_serial_port *port; struct usb_host_interface *iface_desc; @@ -625,7 +642,7 @@ int usb_serial_probe(struct usb_interface *interface, struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; struct usb_serial_driver *type = NULL; int retval; - int minor; + unsigned int minor; int buffer_size; int i; int num_interrupt_in = 0; @@ -643,7 +660,7 @@ int usb_serial_probe(struct usb_interface *interface, return -ENODEV; } - serial = create_serial (dev, interface, type); + serial = create_serial(dev, interface, type); if (!serial) { unlock_kernel(); dev_err(&interface->dev, "%s - out of memory\n", __func__); @@ -656,8 +673,9 @@ int usb_serial_probe(struct usb_interface *interface, if (!try_module_get(type->driver.owner)) { unlock_kernel(); - dev_err(&interface->dev, "module get failed, exiting\n"); - kfree (serial); + dev_err(&interface->dev, + "module get failed, exiting\n"); + kfree(serial); return -EIO; } @@ -667,8 +685,8 @@ int usb_serial_probe(struct usb_interface *interface, if (retval) { unlock_kernel(); - dbg ("sub driver rejected device"); - kfree (serial); + dbg("sub driver rejected device"); + kfree(serial); return retval; } } @@ -709,7 +727,7 @@ int usb_serial_probe(struct usb_interface *interface, } #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE) - /* BEGIN HORRIBLE HACK FOR PL2303 */ + /* BEGIN HORRIBLE HACK FOR PL2303 */ /* this is needed due to the looney way its endpoints are set up */ if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) || @@ -738,7 +756,7 @@ int usb_serial_probe(struct usb_interface *interface, if (num_bulk_in == 0 || num_bulk_out == 0) { unlock_kernel(); dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); - kfree (serial); + kfree(serial); return -ENODEV; } } @@ -750,8 +768,9 @@ int usb_serial_probe(struct usb_interface *interface, num_ports = num_bulk_out; if (num_ports == 0) { unlock_kernel(); - dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); - kfree (serial); + dev_err(&interface->dev, + "Generic device with no bulk out, not allowed.\n"); + kfree(serial); return -EIO; } } @@ -761,11 +780,12 @@ int usb_serial_probe(struct usb_interface *interface, if (type->calc_num_ports) { if (!try_module_get(type->driver.owner)) { unlock_kernel(); - dev_err(&interface->dev, "module get failed, exiting\n"); - kfree (serial); + dev_err(&interface->dev, + "module get failed, exiting\n"); + kfree(serial); return -EIO; } - num_ports = type->calc_num_ports (serial); + num_ports = type->calc_num_ports(serial); module_put(type->driver.owner); } if (!num_ports) @@ -783,7 +803,8 @@ int usb_serial_probe(struct usb_interface *interface, type->description); /* create our ports, we need as many as the max endpoints */ - /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */ + /* we don't use num_ports here because some devices have more + endpoint pairs than ports */ max_endpoints = max(num_bulk_in, num_bulk_out); max_endpoints = max(max_endpoints, num_interrupt_in); max_endpoints = max(max_endpoints, num_interrupt_out); @@ -791,7 +812,8 @@ int usb_serial_probe(struct usb_interface *interface, serial->num_port_pointers = max_endpoints; unlock_kernel(); - dbg("%s - setting up %d port structures for this device", __func__, max_endpoints); + dbg("%s - setting up %d port structures for this device", + __func__, max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); if (!port) @@ -807,7 +829,7 @@ int usb_serial_probe(struct usb_interface *interface, for (i = 0; i < num_bulk_in; ++i) { endpoint = bulk_in_endpoint[i]; port = serial->port[i]; - port->read_urb = usb_alloc_urb (0, GFP_KERNEL); + port->read_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->read_urb) { dev_err(&interface->dev, "No free urbs available\n"); goto probe_error; @@ -815,17 +837,17 @@ int usb_serial_probe(struct usb_interface *interface, buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->bulk_in_size = buffer_size; port->bulk_in_endpointAddress = endpoint->bEndpointAddress; - port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!port->bulk_in_buffer) { - dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n"); + dev_err(&interface->dev, + "Couldn't allocate bulk_in_buffer\n"); goto probe_error; } - usb_fill_bulk_urb (port->read_urb, dev, - usb_rcvbulkpipe (dev, - endpoint->bEndpointAddress), - port->bulk_in_buffer, buffer_size, - serial->type->read_bulk_callback, - port); + usb_fill_bulk_urb(port->read_urb, dev, + usb_rcvbulkpipe(dev, + endpoint->bEndpointAddress), + port->bulk_in_buffer, buffer_size, + serial->type->read_bulk_callback, port); } for (i = 0; i < num_bulk_out; ++i) { @@ -839,17 +861,17 @@ int usb_serial_probe(struct usb_interface *interface, buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->bulk_out_size = buffer_size; port->bulk_out_endpointAddress = endpoint->bEndpointAddress; - port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); + port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!port->bulk_out_buffer) { - dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n"); + dev_err(&interface->dev, + "Couldn't allocate bulk_out_buffer\n"); goto probe_error; } - usb_fill_bulk_urb (port->write_urb, dev, - usb_sndbulkpipe (dev, - endpoint->bEndpointAddress), - port->bulk_out_buffer, buffer_size, - serial->type->write_bulk_callback, - port); + usb_fill_bulk_urb(port->write_urb, dev, + usb_sndbulkpipe(dev, + endpoint->bEndpointAddress), + port->bulk_out_buffer, buffer_size, + serial->type->write_bulk_callback, port); } if (serial->type->read_int_callback) { @@ -858,73 +880,82 @@ int usb_serial_probe(struct usb_interface *interface, port = serial->port[i]; port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->interrupt_in_urb) { - dev_err(&interface->dev, "No free urbs available\n"); + dev_err(&interface->dev, + "No free urbs available\n"); goto probe_error; } buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - port->interrupt_in_endpointAddress = endpoint->bEndpointAddress; - port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + port->interrupt_in_endpointAddress = + endpoint->bEndpointAddress; + port->interrupt_in_buffer = kmalloc(buffer_size, + GFP_KERNEL); if (!port->interrupt_in_buffer) { - dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n"); + dev_err(&interface->dev, + "Couldn't allocate interrupt_in_buffer\n"); goto probe_error; } - usb_fill_int_urb (port->interrupt_in_urb, dev, - usb_rcvintpipe (dev, - endpoint->bEndpointAddress), - port->interrupt_in_buffer, buffer_size, - serial->type->read_int_callback, port, - endpoint->bInterval); + usb_fill_int_urb(port->interrupt_in_urb, dev, + usb_rcvintpipe(dev, + endpoint->bEndpointAddress), + port->interrupt_in_buffer, buffer_size, + serial->type->read_int_callback, port, + endpoint->bInterval); } } else if (num_interrupt_in) { dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined"); } - + if (serial->type->write_int_callback) { for (i = 0; i < num_interrupt_out; ++i) { endpoint = interrupt_out_endpoint[i]; port = serial->port[i]; port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->interrupt_out_urb) { - dev_err(&interface->dev, "No free urbs available\n"); + dev_err(&interface->dev, + "No free urbs available\n"); goto probe_error; } buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->interrupt_out_size = buffer_size; - port->interrupt_out_endpointAddress = endpoint->bEndpointAddress; - port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL); + port->interrupt_out_endpointAddress = + endpoint->bEndpointAddress; + port->interrupt_out_buffer = kmalloc(buffer_size, + GFP_KERNEL); if (!port->interrupt_out_buffer) { - dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n"); + dev_err(&interface->dev, + "Couldn't allocate interrupt_out_buffer\n"); goto probe_error; } - usb_fill_int_urb (port->interrupt_out_urb, dev, - usb_sndintpipe (dev, - endpoint->bEndpointAddress), - port->interrupt_out_buffer, buffer_size, - serial->type->write_int_callback, port, - endpoint->bInterval); + usb_fill_int_urb(port->interrupt_out_urb, dev, + usb_sndintpipe(dev, + endpoint->bEndpointAddress), + port->interrupt_out_buffer, buffer_size, + serial->type->write_int_callback, port, + endpoint->bInterval); } } else if (num_interrupt_out) { dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); } - + /* if this device type has an attach function, call it */ if (type->attach) { if (!try_module_get(type->driver.owner)) { - dev_err(&interface->dev, "module get failed, exiting\n"); + dev_err(&interface->dev, + "module get failed, exiting\n"); goto probe_error; } - retval = type->attach (serial); + retval = type->attach(serial); module_put(type->driver.owner); if (retval < 0) goto probe_error; if (retval > 0) { - /* quietly accept this device, but don't bind to a serial port - * as it's about to disappear */ + /* quietly accept this device, but don't bind to a + serial port as it's about to disappear */ goto exit; } } - if (get_free_serial (serial, num_ports, &minor) == NULL) { + if (get_free_serial(serial, num_ports, &minor) == NULL) { dev_err(&interface->dev, "No more free serial devices\n"); goto probe_error; } @@ -938,19 +969,19 @@ int usb_serial_probe(struct usb_interface *interface, port->dev.bus = &usb_serial_bus_type; port->dev.release = &port_release; - snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number); - dbg ("%s - registering %s", __func__, port->dev.bus_id); + dev_set_name(&port->dev, "ttyUSB%d", port->number); + dbg ("%s - registering %s", __func__, dev_name(&port->dev)); retval = device_register(&port->dev); if (retval) dev_err(&port->dev, "Error registering port device, " "continuing\n"); } - usb_serial_console_init (debug, minor); + usb_serial_console_init(debug, minor); exit: /* success */ - usb_set_intfdata (interface, serial); + usb_set_intfdata(interface, serial); return 0; probe_error: @@ -986,29 +1017,30 @@ probe_error: /* free up any memory that we allocated */ for (i = 0; i < serial->num_port_pointers; ++i) kfree(serial->port[i]); - kfree (serial); + kfree(serial); return -EIO; } +EXPORT_SYMBOL_GPL(usb_serial_probe); void usb_serial_disconnect(struct usb_interface *interface) { int i; - struct usb_serial *serial = usb_get_intfdata (interface); + struct usb_serial *serial = usb_get_intfdata(interface); struct device *dev = &interface->dev; struct usb_serial_port *port; usb_serial_console_disconnect(serial); - dbg ("%s", __func__); + dbg("%s", __func__); mutex_lock(&serial->disc_mutex); - usb_set_intfdata (interface, NULL); + usb_set_intfdata(interface, NULL); /* must set a flag, to signal subdrivers */ serial->disconnected = 1; for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) { - if (port->tty) - tty_hangup(port->tty); + if (port->port.tty) + tty_hangup(port->port.tty); kill_traffic(port); } } @@ -1018,6 +1050,7 @@ void usb_serial_disconnect(struct usb_interface *interface) usb_serial_put(serial); dev_info(dev, "device disconnected\n"); } +EXPORT_SYMBOL_GPL(usb_serial_disconnect); int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) { @@ -1076,9 +1109,8 @@ static int __init usb_serial_init(void) return -ENOMEM; /* Initialize our global data */ - for (i = 0; i < SERIAL_TTY_MINORS; ++i) { + for (i = 0; i < SERIAL_TTY_MINORS; ++i) serial_table[i] = NULL; - } result = bus_register(&usb_serial_bus_type); if (result) { @@ -1093,9 +1125,11 @@ static int __init usb_serial_init(void) usb_serial_tty_driver->minor_start = 0; usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; - usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV; usb_serial_tty_driver->init_termios = tty_std_termios; - usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD + | HUPCL | CLOCAL; usb_serial_tty_driver->init_termios.c_ispeed = 9600; usb_serial_tty_driver->init_termios.c_ospeed = 9600; tty_set_operations(usb_serial_tty_driver, &serial_ops); @@ -1133,7 +1167,7 @@ exit_reg_driver: bus_unregister(&usb_serial_bus_type); exit_bus: - err ("%s - returning with error %d", __func__, result); + err("%s - returning with error %d", __func__, result); put_tty_driver(usb_serial_tty_driver); return result; } @@ -1160,7 +1194,7 @@ module_exit(usb_serial_exit); if (!type->function) { \ type->function = usb_serial_generic_##function; \ dbg("Had to override the " #function \ - " usb serial operation with the generic one.");\ + " usb serial operation with the generic one.");\ } \ } while (0) @@ -1177,8 +1211,9 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, resume); } -int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ +int usb_serial_register(struct usb_serial_driver *driver) { + /* must be called with BKL held */ int retval; fixup_generic(driver); @@ -1191,37 +1226,30 @@ int usb_serial_register(struct usb_serial_driver *driver) /* must be called with retval = usb_serial_bus_register(driver); if (retval) { - err("problem %d when registering driver %s", retval, driver->description); + err("problem %d when registering driver %s", + retval, driver->description); list_del(&driver->driver_list); - } - else - info("USB Serial support registered for %s", driver->description); + } else + info("USB Serial support registered for %s", + driver->description); return retval; } +EXPORT_SYMBOL_GPL(usb_serial_register); -void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */ +void usb_serial_deregister(struct usb_serial_driver *device) { + /* must be called with BKL held */ info("USB Serial deregistering driver %s", device->description); list_del(&device->driver_list); usb_serial_bus_deregister(device); } - - - -/* If the usb-serial core is built into the core, the usb-serial drivers - need these symbols to load properly as modules. */ -EXPORT_SYMBOL_GPL(usb_serial_register); EXPORT_SYMBOL_GPL(usb_serial_deregister); -EXPORT_SYMBOL_GPL(usb_serial_probe); -EXPORT_SYMBOL_GPL(usb_serial_disconnect); -EXPORT_SYMBOL_GPL(usb_serial_port_softint); - /* Module information */ -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index f9fc926b56d8..fc5d9952b03b 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -15,6 +15,8 @@ #include <linux/usb.h> #include <linux/usb/serial.h> +#define USB_DEBUG_MAX_PACKET_SIZE 8 + static struct usb_device_id id_table [] = { { USB_DEVICE(0x0525, 0x127a) }, { }, @@ -29,6 +31,13 @@ static struct usb_driver debug_driver = { .no_dynamic_id = 1, }; +int usb_debug_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + port->bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE; + return usb_serial_generic_open(tty, port, filp); +} + static struct usb_serial_driver debug_device = { .driver = { .owner = THIS_MODULE, @@ -36,6 +45,7 @@ static struct usb_serial_driver debug_device = { }, .id_table = id_table, .num_ports = 1, + .open = usb_debug_open, }; static int __init debug_init(void) diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 5fc20122145f..cf8924f9a2cc 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -9,7 +9,8 @@ * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * */ @@ -23,7 +24,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "visor.h" @@ -35,25 +36,29 @@ #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver" /* function prototypes for a handspring visor */ -static int visor_open (struct usb_serial_port *port, struct file *filp); -static void visor_close (struct usb_serial_port *port, struct file *filp); -static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static int visor_write_room (struct usb_serial_port *port); -static int visor_chars_in_buffer (struct usb_serial_port *port); -static void visor_throttle (struct usb_serial_port *port); -static void visor_unthrottle (struct usb_serial_port *port); -static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id); +static int visor_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static void visor_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp); +static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static int visor_write_room(struct tty_struct *tty); +static void visor_throttle(struct tty_struct *tty); +static void visor_unthrottle(struct tty_struct *tty); +static int visor_probe(struct usb_serial *serial, + const struct usb_device_id *id); static int visor_calc_num_ports(struct usb_serial *serial); -static void visor_shutdown (struct usb_serial *serial); -static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void visor_write_bulk_callback (struct urb *urb); -static void visor_read_bulk_callback (struct urb *urb); -static void visor_read_int_callback (struct urb *urb); -static int clie_3_5_startup (struct usb_serial *serial); -static int treo_attach (struct usb_serial *serial); -static int clie_5_attach (struct usb_serial *serial); -static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id); -static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id); +static void visor_shutdown(struct usb_serial *serial); +static void visor_write_bulk_callback(struct urb *urb); +static void visor_read_bulk_callback(struct urb *urb); +static void visor_read_int_callback(struct urb *urb); +static int clie_3_5_startup(struct usb_serial *serial); +static int treo_attach(struct usb_serial *serial); +static int clie_5_attach(struct usb_serial *serial); +static int palm_os_3_probe(struct usb_serial *serial, + const struct usb_device_id *id); +static int palm_os_4_probe(struct usb_serial *serial, + const struct usb_device_id *id); /* Parameters that may be passed into the module. */ static int debug; @@ -105,13 +110,13 @@ static struct usb_device_id id_table [] = { .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, - { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), + { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, - { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), + { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, - { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), + { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, @@ -170,7 +175,7 @@ static struct usb_device_id id_table_combined [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver visor_driver = { .name = "visor", @@ -180,7 +185,8 @@ static struct usb_driver visor_driver = { .no_dynamic_id = 1, }; -/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */ +/* All of the device info needed for the Handspring Visor, + and Palm 4.0 devices */ static struct usb_serial_driver handspring_device = { .driver = { .owner = THIS_MODULE, @@ -198,10 +204,8 @@ static struct usb_serial_driver handspring_device = { .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, .shutdown = visor_shutdown, - .ioctl = visor_ioctl, .write = visor_write, .write_room = visor_write_room, - .chars_in_buffer = visor_chars_in_buffer, .write_bulk_callback = visor_write_bulk_callback, .read_bulk_callback = visor_read_bulk_callback, .read_int_callback = visor_read_int_callback, @@ -225,10 +229,8 @@ static struct usb_serial_driver clie_5_device = { .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, .shutdown = visor_shutdown, - .ioctl = visor_ioctl, .write = visor_write, .write_room = visor_write_room, - .chars_in_buffer = visor_chars_in_buffer, .write_bulk_callback = visor_write_bulk_callback, .read_bulk_callback = visor_read_bulk_callback, .read_int_callback = visor_read_int_callback, @@ -249,10 +251,8 @@ static struct usb_serial_driver clie_3_5_device = { .throttle = visor_throttle, .unthrottle = visor_unthrottle, .attach = clie_3_5_startup, - .ioctl = visor_ioctl, .write = visor_write, .write_room = visor_write_room, - .chars_in_buffer = visor_chars_in_buffer, .write_bulk_callback = visor_write_bulk_callback, .read_bulk_callback = visor_read_bulk_callback, }; @@ -274,7 +274,8 @@ static int stats; /****************************************************************************** * Handspring Visor specific driver functions ******************************************************************************/ -static int visor_open (struct usb_serial_port *port, struct file *filp) +static int visor_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) { struct usb_serial *serial = port->serial; struct visor_private *priv = usb_get_serial_port_data(port); @@ -300,42 +301,45 @@ static int visor_open (struct usb_serial_port *port, struct file *filp) * through, otherwise it is scheduled, and with high data rates (like * with OHCI) data can get lost. */ - if (port->tty) - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; /* Start reading from the device */ - usb_fill_bulk_urb (port->read_urb, serial->dev, - usb_rcvbulkpipe (serial->dev, + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, visor_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) { - dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); goto exit; } - + if (port->interrupt_in_urb) { dbg("%s - adding interrupt input for treo", __func__); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) - dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting interrupt urb, error %d\n", + __func__, result); } -exit: +exit: return result; } -static void visor_close (struct usb_serial_port *port, struct file * filp) +static void visor_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct visor_private *priv = usb_get_serial_port_data(port); unsigned char *transfer_buffer; dbg("%s - port %d", __func__, port->number); - + /* shutdown our urbs */ usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); @@ -343,14 +347,14 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) mutex_lock(&port->serial->disc_mutex); if (!port->serial->disconnected) { /* Try to send shutdown message, unless the device is gone */ - transfer_buffer = kmalloc (0x12, GFP_KERNEL); + transfer_buffer = kmalloc(0x12, GFP_KERNEL); if (transfer_buffer) { - usb_control_msg (port->serial->dev, + usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), VISOR_CLOSE_NOTIFICATION, 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); - kfree (transfer_buffer); + kfree(transfer_buffer); } } mutex_unlock(&port->serial->disc_mutex); @@ -361,7 +365,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) } -static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count) +static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { struct visor_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; @@ -381,7 +386,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf, priv->outstanding_urbs++; spin_unlock_irqrestore(&priv->lock, flags); - buffer = kmalloc (count, GFP_ATOMIC); + buffer = kmalloc(count, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; @@ -395,21 +400,22 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf, goto error_no_urb; } - memcpy (buffer, buf, count); + memcpy(buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); - usb_fill_bulk_urb (urb, serial->dev, - usb_sndbulkpipe (serial->dev, + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), - buffer, count, + buffer, count, visor_write_bulk_callback, port); /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { - dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", - __func__, status); + dev_err(&port->dev, + "%s - usb_submit_urb(write bulk) failed with status = %d\n", + __func__, status); count = status; goto error; } else { @@ -435,8 +441,9 @@ error_no_buffer: } -static int visor_write_room (struct usb_serial_port *port) +static int visor_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct visor_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -460,23 +467,7 @@ static int visor_write_room (struct usb_serial_port *port) } -static int visor_chars_in_buffer (struct usb_serial_port *port) -{ - dbg("%s - port %d", __func__, port->number); - - /* - * We can't really account for how much data we - * have sent out, but hasn't made it through to the - * device, so just tell the tty layer that everything - * is flushed. - * - * FIXME: Should walk outstanding_urbs - */ - return 0; -} - - -static void visor_write_bulk_callback (struct urb *urb) +static void visor_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct visor_private *priv = usb_get_serial_port_data(port); @@ -484,7 +475,7 @@ static void visor_write_bulk_callback (struct urb *urb) unsigned long flags; /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree (urb->transfer_buffer); + kfree(urb->transfer_buffer); dbg("%s - port %d", __func__, port->number); @@ -500,7 +491,7 @@ static void visor_write_bulk_callback (struct urb *urb) } -static void visor_read_bulk_callback (struct urb *urb) +static void visor_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct visor_private *priv = usb_get_serial_port_data(port); @@ -518,11 +509,13 @@ static void visor_read_bulk_callback (struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); - tty = port->tty; + tty = port->port.tty; if (tty && urb->actual_length) { - available_room = tty_buffer_request_room(tty, urb->actual_length); + available_room = tty_buffer_request_room(tty, + urb->actual_length); if (available_room) { tty_insert_flip_string(tty, data, available_room); tty_flip_buffer_push(tty); @@ -536,22 +529,23 @@ static void visor_read_bulk_callback (struct urb *urb) /* Continue trying to always read if we should */ if (!priv->throttled) { - usb_fill_bulk_urb (port->read_urb, port->serial->dev, + usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), + port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, visor_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); - } else { + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); + } else priv->actually_throttled = 1; - } spin_unlock(&priv->lock); } -static void visor_read_int_callback (struct urb *urb) +static void visor_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; int status = urb->status; @@ -585,14 +579,16 @@ static void visor_read_int_callback (struct urb *urb) urb->actual_length, urb->transfer_buffer); exit: - result = usb_submit_urb (urb, GFP_ATOMIC); + result = usb_submit_urb(urb, GFP_ATOMIC); if (result) - dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", - __func__, result); + dev_err(&urb->dev->dev, + "%s - Error %d submitting interrupt urb\n", + __func__, result); } -static void visor_throttle (struct usb_serial_port *port) +static void visor_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct visor_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -603,8 +599,9 @@ static void visor_throttle (struct usb_serial_port *port) } -static void visor_unthrottle (struct usb_serial_port *port) +static void visor_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct visor_private *priv = usb_get_serial_port_data(port); unsigned long flags; int result; @@ -618,10 +615,13 @@ static void visor_unthrottle (struct usb_serial_port *port) port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); } -static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id) +static int palm_os_3_probe(struct usb_serial *serial, + const struct usb_device_id *id) { struct device *dev = &serial->dev->dev; struct visor_connection_info *connection_info; @@ -633,7 +633,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i dbg("%s", __func__); - transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL); + transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL); if (!transfer_buffer) { dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__, sizeof(*connection_info)); @@ -641,7 +641,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i } /* send a get connection info request */ - retval = usb_control_msg (serial->dev, + retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION, 0xc2, 0x0000, 0x0000, transfer_buffer, @@ -653,29 +653,31 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i } if (retval == sizeof(*connection_info)) { - connection_info = (struct visor_connection_info *)transfer_buffer; + connection_info = (struct visor_connection_info *) + transfer_buffer; num_ports = le16_to_cpu(connection_info->num_ports); for (i = 0; i < num_ports; ++i) { - switch (connection_info->connections[i].port_function_id) { - case VISOR_FUNCTION_GENERIC: - string = "Generic"; - break; - case VISOR_FUNCTION_DEBUGGER: - string = "Debugger"; - break; - case VISOR_FUNCTION_HOTSYNC: - string = "HotSync"; - break; - case VISOR_FUNCTION_CONSOLE: - string = "Console"; - break; - case VISOR_FUNCTION_REMOTE_FILE_SYS: - string = "Remote File System"; - break; - default: - string = "unknown"; - break; + switch ( + connection_info->connections[i].port_function_id) { + case VISOR_FUNCTION_GENERIC: + string = "Generic"; + break; + case VISOR_FUNCTION_DEBUGGER: + string = "Debugger"; + break; + case VISOR_FUNCTION_HOTSYNC: + string = "HotSync"; + break; + case VISOR_FUNCTION_CONSOLE: + string = "Console"; + break; + case VISOR_FUNCTION_REMOTE_FILE_SYS: + string = "Remote File System"; + break; + default: + string = "unknown"; + break; } dev_info(dev, "%s: port %d, is for %s use\n", serial->type->description, @@ -686,11 +688,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i * Handle devices that report invalid stuff here. */ if (num_ports == 0 || num_ports > 2) { - dev_warn (dev, "%s: No valid connect info available\n", + dev_warn(dev, "%s: No valid connect info available\n", serial->type->description); num_ports = 2; } - + dev_info(dev, "%s: Number of ports: %d\n", serial->type->description, num_ports); @@ -700,8 +702,9 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i */ usb_set_serial_data(serial, (void *)(long)num_ports); - /* ask for the number of bytes available, but ignore the response as it is broken */ - retval = usb_control_msg (serial->dev, + /* ask for the number of bytes available, but ignore the + response as it is broken */ + retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, 0xc2, 0x0000, 0x0005, transfer_buffer, @@ -712,12 +715,13 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i retval = 0; exit: - kfree (transfer_buffer); + kfree(transfer_buffer); return retval; } -static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id) +static int palm_os_4_probe(struct usb_serial *serial, + const struct usb_device_id *id) { struct device *dev = &serial->dev->dev; struct palm_ext_connection_info *connection_info; @@ -726,18 +730,18 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i dbg("%s", __func__); - transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL); + transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL); if (!transfer_buffer) { dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__, sizeof(*connection_info)); return -ENOMEM; } - retval = usb_control_msg (serial->dev, - usb_rcvctrlpipe(serial->dev, 0), + retval = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), PALM_GET_EXT_CONNECTION_INFORMATION, 0xc2, 0x0000, 0x0000, transfer_buffer, - sizeof (*connection_info), 300); + sizeof(*connection_info), 300); if (retval < 0) dev_err(dev, "%s - error %d getting connection info\n", __func__, retval); @@ -745,15 +749,17 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i usb_serial_debug_data(debug, &serial->dev->dev, __func__, retval, transfer_buffer); - kfree (transfer_buffer); + kfree(transfer_buffer); return 0; } -static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id) +static int visor_probe(struct usb_serial *serial, + const struct usb_device_id *id) { int retval = 0; - int (*startup) (struct usb_serial *serial, const struct usb_device_id *id); + int (*startup)(struct usb_serial *serial, + const struct usb_device_id *id); dbg("%s", __func__); @@ -771,7 +777,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id *i return retval; } -static int visor_calc_num_ports (struct usb_serial *serial) +static int visor_calc_num_ports(struct usb_serial *serial) { int num_ports = (int)(long)(usb_get_serial_data(serial)); @@ -788,7 +794,7 @@ static int generic_startup(struct usb_serial *serial) int i; for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc (sizeof(*priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { while (i-- != 0) { priv = usb_get_serial_port_data(ports[i]); @@ -803,7 +809,7 @@ static int generic_startup(struct usb_serial *serial) return 0; } -static int clie_3_5_startup (struct usb_serial *serial) +static int clie_3_5_startup(struct usb_serial *serial) { struct device *dev = &serial->dev->dev; int result; @@ -816,62 +822,72 @@ static int clie_3_5_startup (struct usb_serial *serial) */ /* get the config number */ - result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQ_GET_CONFIGURATION, USB_DIR_IN, 0, 0, &data, 1, 3000); if (result < 0) { - dev_err(dev, "%s: get config number failed: %d\n", __func__, result); + dev_err(dev, "%s: get config number failed: %d\n", + __func__, result); return result; } if (result != 1) { - dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result); + dev_err(dev, "%s: get config number bad return length: %d\n", + __func__, result); return -EIO; } /* get the interface number */ - result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), - USB_REQ_GET_INTERFACE, + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + USB_REQ_GET_INTERFACE, USB_DIR_IN | USB_RECIP_INTERFACE, 0, 0, &data, 1, 3000); if (result < 0) { - dev_err(dev, "%s: get interface number failed: %d\n", __func__, result); + dev_err(dev, "%s: get interface number failed: %d\n", + __func__, result); return result; } if (result != 1) { - dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result); + dev_err(dev, + "%s: get interface number bad return length: %d\n", + __func__, result); return -EIO; } return generic_startup(serial); } - -static int treo_attach (struct usb_serial *serial) + +static int treo_attach(struct usb_serial *serial) { struct usb_serial_port *swap_port; /* Only do this endpoint hack for the Handspring devices with * interrupt in endpoints, which for now are the Treo devices. */ - if (!((le16_to_cpu(serial->dev->descriptor.idVendor) == HANDSPRING_VENDOR_ID) || - (le16_to_cpu(serial->dev->descriptor.idVendor) == KYOCERA_VENDOR_ID)) || - (serial->num_interrupt_in == 0)) + if (!((le16_to_cpu(serial->dev->descriptor.idVendor) + == HANDSPRING_VENDOR_ID) || + (le16_to_cpu(serial->dev->descriptor.idVendor) + == KYOCERA_VENDOR_ID)) || + (serial->num_interrupt_in == 0)) goto generic_startup; dbg("%s", __func__); /* - * It appears that Treos and Kyoceras want to use the - * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, - * so let's swap the 1st and 2nd bulk in and interrupt endpoints. - * Note that swapping the bulk out endpoints would break lots of + * It appears that Treos and Kyoceras want to use the + * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, + * so let's swap the 1st and 2nd bulk in and interrupt endpoints. + * Note that swapping the bulk out endpoints would break lots of * apps that want to communicate on the second port. */ #define COPY_PORT(dest, src) \ - dest->read_urb = src->read_urb; \ - dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress; \ - dest->bulk_in_buffer = src->bulk_in_buffer; \ - dest->interrupt_in_urb = src->interrupt_in_urb; \ - dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress; \ - dest->interrupt_in_buffer = src->interrupt_in_buffer; + do { \ + dest->read_urb = src->read_urb; \ + dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\ + dest->bulk_in_buffer = src->bulk_in_buffer; \ + dest->interrupt_in_urb = src->interrupt_in_urb; \ + dest->interrupt_in_endpointAddress = \ + src->interrupt_in_endpointAddress;\ + dest->interrupt_in_buffer = src->interrupt_in_buffer; \ + } while (0); swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL); if (!swap_port) @@ -885,28 +901,30 @@ generic_startup: return generic_startup(serial); } -static int clie_5_attach (struct usb_serial *serial) +static int clie_5_attach(struct usb_serial *serial) { dbg("%s", __func__); - /* TH55 registers 2 ports. - Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0 - Communication out to the UX50/TH55 uses bulk_out_endpointAddress from port 1 - + /* TH55 registers 2 ports. + Communication in from the UX50/TH55 uses bulk_in_endpointAddress + from port 0. Communication out to the UX50/TH55 uses + bulk_out_endpointAddress from port 1 + Lets do a quick and dirty mapping */ - + /* some sanity check */ if (serial->num_ports < 2) return -1; - + /* port 0 now uses the modified endpoint Address */ - serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress; + serial->port[0]->bulk_out_endpointAddress = + serial->port[1]->bulk_out_endpointAddress; return generic_startup(serial); } -static void visor_shutdown (struct usb_serial *serial) +static void visor_shutdown(struct usb_serial *serial) { struct visor_private *priv; int i; @@ -922,37 +940,35 @@ static void visor_shutdown (struct usb_serial *serial) } } -static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) -{ - dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); - - return -ENOIOCTLCMD; -} - -static int __init visor_init (void) +static int __init visor_init(void) { int i, retval; /* Only if parameters were passed to us */ - if ((vendor>0) && (product>0)) { - struct usb_device_id usb_dev_temp[]= - {{USB_DEVICE(vendor, product), - .driver_info = (kernel_ulong_t)&palm_os_4_probe }}; + if (vendor > 0 && product > 0) { + struct usb_device_id usb_dev_temp[] = { + { + USB_DEVICE(vendor, product), + .driver_info = + (kernel_ulong_t) &palm_os_4_probe + } + }; /* Find the last entry in id_table */ - for (i=0; ; i++) { - if (id_table[i].idVendor==0) { + for (i = 0;; i++) { + if (id_table[i].idVendor == 0) { id_table[i] = usb_dev_temp[0]; break; } } /* Find the last entry in id_table_combined */ - for (i=0; ; i++) { - if (id_table_combined[i].idVendor==0) { + for (i = 0;; i++) { + if (id_table_combined[i].idVendor == 0) { id_table_combined[i] = usb_dev_temp[0]; break; } } - info("Untested USB device specified at time of module insertion"); + info( + "Untested USB device specified at time of module insertion"); info("Warning: This is not guaranteed to work"); info("Using a newer kernel is preferred to this method"); info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x", @@ -968,7 +984,7 @@ static int __init visor_init (void) if (retval) goto failed_clie_5_register; retval = usb_register(&visor_driver); - if (retval) + if (retval) goto failed_usb_register; info(DRIVER_DESC); @@ -986,18 +1002,18 @@ failed_handspring_register: static void __exit visor_exit (void) { - usb_deregister (&visor_driver); - usb_serial_deregister (&handspring_device); - usb_serial_deregister (&clie_3_5_device); - usb_serial_deregister (&clie_5_device); + usb_deregister(&visor_driver); + usb_serial_deregister(&handspring_device); + usb_serial_deregister(&clie_3_5_device); + usb_serial_deregister(&clie_5_device); } module_init(visor_init); module_exit(visor_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 665aa77a917b..3a9d14384a43 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -12,29 +12,31 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * (10/09/2002) Stuart MacDonald (stuartm@connecttech.com) * Upgrade to full working driver * * (05/30/2001) gkh - * switched from using spinlock to a semaphore, which fixes lots of problems. + * switched from using spinlock to a semaphore, which fixes lots of + * problems. * * (04/08/2001) gb * Identify version on module load. - * + * * 2001_Mar_19 gkh - * Fixed MOD_INC and MOD_DEC logic, the ability to open a port more + * Fixed MOD_INC and MOD_DEC logic, the ability to open a port more * than once, and the got the proper usb_device_id table entries so * the driver works again. * * (11/01/2000) Adam J. Richter * usb_device_id table support - * + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. - * + * * (10/03/2000) smd * firmware is improved to guard against crap sent to device * firmware now replies CMD_FAILURE on bad things @@ -52,9 +54,9 @@ * Fixed bug with port->minor that was found by Al Borchers * * (07/04/2000) gkh - * Added support for port settings. Baud rate can now be changed. Line signals - * are not transferred to and from the tty layer yet, but things seem to be - * working well now. + * Added support for port settings. Baud rate can now be changed. Line + * signals are not transferred to and from the tty layer yet, but things + * seem to be working well now. * * (05/04/2000) gkh * First cut at open and close commands. Data can flow through the ports at @@ -62,7 +64,7 @@ * * (03/26/2000) gkh * Split driver up into device specific pieces. - * + * */ #include <linux/kernel.h> @@ -75,7 +77,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/mutex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/termbits.h> #include <linux/usb.h> #include <linux/serial_reg.h> @@ -125,7 +127,7 @@ static struct usb_device_id id_table_combined [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver whiteheat_driver = { .name = "whiteheat", @@ -136,26 +138,34 @@ static struct usb_driver whiteheat_driver = { }; /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */ -static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id); -static int whiteheat_firmware_attach (struct usb_serial *serial); +static int whiteheat_firmware_download(struct usb_serial *serial, + const struct usb_device_id *id); +static int whiteheat_firmware_attach(struct usb_serial *serial); /* function prototypes for the Connect Tech WhiteHEAT serial converter */ -static int whiteheat_attach (struct usb_serial *serial); -static void whiteheat_shutdown (struct usb_serial *serial); -static int whiteheat_open (struct usb_serial_port *port, struct file *filp); -static void whiteheat_close (struct usb_serial_port *port, struct file *filp); -static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static int whiteheat_write_room (struct usb_serial_port *port); -static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old); -static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file); -static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); -static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state); -static int whiteheat_chars_in_buffer (struct usb_serial_port *port); -static void whiteheat_throttle (struct usb_serial_port *port); -static void whiteheat_unthrottle (struct usb_serial_port *port); -static void whiteheat_read_callback (struct urb *urb); -static void whiteheat_write_callback (struct urb *urb); +static int whiteheat_attach(struct usb_serial *serial); +static void whiteheat_shutdown(struct usb_serial *serial); +static int whiteheat_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void whiteheat_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static int whiteheat_write(struct tty_struct *tty, + struct usb_serial_port *port, + const unsigned char *buf, int count); +static int whiteheat_write_room(struct tty_struct *tty); +static int whiteheat_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void whiteheat_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file); +static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static void whiteheat_break_ctl(struct tty_struct *tty, int break_state); +static int whiteheat_chars_in_buffer(struct tty_struct *tty); +static void whiteheat_throttle(struct tty_struct *tty); +static void whiteheat_unthrottle(struct tty_struct *tty); +static void whiteheat_read_callback(struct urb *urb); +static void whiteheat_write_callback(struct urb *urb); static struct usb_serial_driver whiteheat_fake_device = { .driver = { @@ -202,7 +212,9 @@ struct whiteheat_command_private { struct mutex mutex; __u8 port_running; __u8 command_finished; - wait_queue_head_t wait_command; /* for handling sleeping while waiting for a command to finish */ + wait_queue_head_t wait_command; /* for handling sleeping whilst + waiting for a command to + finish */ __u8 result_buffer[64]; }; @@ -239,14 +251,16 @@ static void command_port_write_callback(struct urb *urb); static void command_port_read_callback(struct urb *urb); static int start_port_read(struct usb_serial_port *port); -static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head); +static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, + struct list_head *head); static struct list_head *list_first(struct list_head *head); static void rx_data_softint(struct work_struct *work); -static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize); +static int firm_send_command(struct usb_serial_port *port, __u8 command, + __u8 *data, __u8 datasize); static int firm_open(struct usb_serial_port *port); static int firm_close(struct usb_serial_port *port); -static int firm_setup_port(struct usb_serial_port *port); +static int firm_setup_port(struct tty_struct *tty); static int firm_set_rts(struct usb_serial_port *port, __u8 onoff); static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff); static int firm_set_break(struct usb_serial_port *port, __u8 onoff); @@ -278,7 +292,8 @@ static int firm_report_tx_done(struct usb_serial_port *port); - device renumerated itself and comes up as new device id with all firmware download completed. */ -static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id) +static int whiteheat_firmware_download(struct usb_serial *serial, + const struct usb_device_id *id) { int response, ret = -ENOENT; const struct firmware *loader_fw = NULL, *firmware_fw = NULL; @@ -313,7 +328,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct record = ihex_next_binrec(record); } - response = ezusb_set_reset (serial, 0); + response = ezusb_set_reset(serial, 0); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) @@ -330,8 +345,8 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct } ++record; } - - response = ezusb_set_reset (serial, 1); + + response = ezusb_set_reset(serial, 1); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) { @@ -355,7 +370,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct } -static int whiteheat_firmware_attach (struct usb_serial *serial) +static int whiteheat_firmware_attach(struct usb_serial *serial) { /* We want this device to fail to have a driver assigned to it */ return 1; @@ -365,7 +380,7 @@ static int whiteheat_firmware_attach (struct usb_serial *serial) /***************************************************************************** * Connect Tech's White Heat serial driver functions *****************************************************************************/ -static int whiteheat_attach (struct usb_serial *serial) +static int whiteheat_attach(struct usb_serial *serial) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; @@ -386,43 +401,52 @@ static int whiteheat_attach (struct usb_serial *serial) command_port = serial->port[COMMAND_PORT]; - pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress); + pipe = usb_sndbulkpipe(serial->dev, + command_port->bulk_out_endpointAddress); command = kmalloc(2, GFP_KERNEL); if (!command) goto no_command_buffer; command[0] = WHITEHEAT_GET_HW_INFO; command[1] = 0; - + result = kmalloc(sizeof(*hw_info) + 1, GFP_KERNEL); if (!result) goto no_result_buffer; /* * When the module is reloaded the firmware is still there and * the endpoints are still in the usb core unchanged. This is the - * unlinking bug in disguise. Same for the call below. - */ + * unlinking bug in disguise. Same for the call below. + */ usb_clear_halt(serial->dev, pipe); - ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS); + ret = usb_bulk_msg(serial->dev, pipe, command, 2, + &alen, COMMAND_TIMEOUT_MS); if (ret) { - err("%s: Couldn't send command [%d]", serial->type->description, ret); + err("%s: Couldn't send command [%d]", + serial->type->description, ret); goto no_firmware; } else if (alen != 2) { - err("%s: Send command incomplete [%d]", serial->type->description, alen); + err("%s: Send command incomplete [%d]", + serial->type->description, alen); goto no_firmware; } - pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress); + pipe = usb_rcvbulkpipe(serial->dev, + command_port->bulk_in_endpointAddress); /* See the comment on the usb_clear_halt() above */ usb_clear_halt(serial->dev, pipe); - ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS); + ret = usb_bulk_msg(serial->dev, pipe, result, + sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS); if (ret) { - err("%s: Couldn't get results [%d]", serial->type->description, ret); + err("%s: Couldn't get results [%d]", + serial->type->description, ret); goto no_firmware; } else if (alen != sizeof(*hw_info) + 1) { - err("%s: Get results incomplete [%d]", serial->type->description, alen); + err("%s: Get results incomplete [%d]", + serial->type->description, alen); goto no_firmware; } else if (result[0] != command[0]) { - err("%s: Command failed [%d]", serial->type->description, result[0]); + err("%s: Command failed [%d]", + serial->type->description, result[0]); goto no_firmware; } @@ -436,7 +460,8 @@ static int whiteheat_attach (struct usb_serial *serial) info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); if (info == NULL) { - err("%s: Out of memory for port structures\n", serial->type->description); + err("%s: Out of memory for port structures\n", + serial->type->description); goto no_private; } @@ -506,9 +531,11 @@ static int whiteheat_attach (struct usb_serial *serial) usb_set_serial_port_data(port, info); } - command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); + command_info = kmalloc(sizeof(struct whiteheat_command_private), + GFP_KERNEL); if (command_info == NULL) { - err("%s: Out of memory for port structures\n", serial->type->description); + err("%s: Out of memory for port structures\n", + serial->type->description); goto no_command_private; } @@ -525,9 +552,12 @@ static int whiteheat_attach (struct usb_serial *serial) no_firmware: /* Firmware likely not running */ - err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description); - err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description); - err("%s: please contact support@connecttech.com\n", serial->type->description); + err("%s: Unable to retrieve firmware version, try replugging\n", + serial->type->description); + err("%s: If the firmware is not running (status led not blinking)\n", + serial->type->description); + err("%s: please contact support@connecttech.com\n", + serial->type->description); kfree(result); return -ENODEV; @@ -570,7 +600,7 @@ no_command_buffer: } -static void whiteheat_shutdown (struct usb_serial *serial) +static void whiteheat_shutdown(struct usb_serial *serial) { struct usb_serial_port *command_port; struct usb_serial_port *port; @@ -585,7 +615,7 @@ static void whiteheat_shutdown (struct usb_serial *serial) /* free up our private data for our command port */ command_port = serial->port[COMMAND_PORT]; - kfree (usb_get_serial_port_data(command_port)); + kfree(usb_get_serial_port_data(command_port)); for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; @@ -612,11 +642,10 @@ static void whiteheat_shutdown (struct usb_serial *serial) return; } - -static int whiteheat_open (struct usb_serial_port *port, struct file *filp) +static int whiteheat_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { int retval = 0; - struct ktermios old_term; dbg("%s - port %d", __func__, port->number); @@ -624,7 +653,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp) if (retval) goto exit; - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; /* send an open port command */ retval = firm_open(port); @@ -640,9 +670,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp) goto exit; } - old_term.c_cflag = ~port->tty->termios->c_cflag; - old_term.c_iflag = ~port->tty->termios->c_iflag; - whiteheat_set_termios(port, &old_term); + if (tty) + firm_setup_port(tty); /* Work around HCD bugs */ usb_clear_halt(port->serial->dev, port->read_urb->pipe); @@ -651,7 +680,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp) /* Start reading from the device */ retval = start_port_read(port); if (retval) { - err("%s - failed submitting read urb, error %d", __func__, retval); + err("%s - failed submitting read urb, error %d", + __func__, retval); firm_close(port); stop_command_port(port->serial); goto exit; @@ -663,7 +693,8 @@ exit: } -static void whiteheat_close(struct usb_serial_port *port, struct file * filp) +static void whiteheat_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct whiteheat_private *info = usb_get_serial_port_data(port); struct whiteheat_urb_wrap *wrap; @@ -681,7 +712,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) } mutex_unlock(&port->serial->disc_mutex); - port->tty->closing = 1; + tty->closing = 1; /* * Not currently in use; tty_wait_until_sent() calls @@ -689,12 +720,12 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) * acquisition. This should be fixed at some point. Greg's been * notified. if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) { - tty_wait_until_sent(port->tty, CLOSING_DELAY); + tty_wait_until_sent(tty, CLOSING_DELAY); } */ - tty_driver_flush_buffer(port->tty); - tty_ldisc_flush(port->tty); + tty_driver_flush_buffer(tty); + tty_ldisc_flush(tty); firm_report_tx_done(port); @@ -728,11 +759,12 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) stop_command_port(port->serial); - port->tty->closing = 0; + tty->closing = 0; } -static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count) +static int whiteheat_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct whiteheat_private *info = usb_get_serial_port_data(port); @@ -763,16 +795,19 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; - bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count; - memcpy (urb->transfer_buffer, buf + sent, bytes); + bytes = (count > port->bulk_out_size) ? + port->bulk_out_size : count; + memcpy(urb->transfer_buffer, buf + sent, bytes); - usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer); + usb_serial_debug_data(debug, &port->dev, + __func__, bytes, urb->transfer_buffer); urb->dev = serial->dev; urb->transfer_buffer_length = bytes; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", __func__, result); + err("%s - failed submitting write urb, error %d", + __func__, result); sent = result; spin_lock_irqsave(&info->lock, flags); list_add(tmp, &info->tx_urbs_free); @@ -790,16 +825,16 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu return sent; } - -static int whiteheat_write_room(struct usb_serial_port *port) +static int whiteheat_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); struct list_head *tmp; int room = 0; unsigned long flags; dbg("%s - port %d", __func__, port->number); - + spin_lock_irqsave(&info->lock, flags); list_for_each(tmp, &info->tx_urbs_free) room++; @@ -810,9 +845,9 @@ static int whiteheat_write_room(struct usb_serial_port *port) return (room); } - -static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file) +static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); unsigned int modem_signals = 0; @@ -827,10 +862,10 @@ static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file) return modem_signals; } - -static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, +static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); dbg("%s - port %d", __func__, port->number); @@ -851,65 +886,55 @@ static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, } -static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +static int whiteheat_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); switch (cmd) { - case TIOCGSERIAL: - memset(&serstruct, 0, sizeof(serstruct)); - serstruct.type = PORT_16654; - serstruct.line = port->serial->minor; - serstruct.port = port->number; - serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; - serstruct.xmit_fifo_size = port->bulk_out_size; - serstruct.custom_divisor = 0; - serstruct.baud_base = 460800; - serstruct.close_delay = CLOSING_DELAY; - serstruct.closing_wait = CLOSING_DELAY; - - if (copy_to_user(user_arg, &serstruct, sizeof(serstruct))) - return -EFAULT; - - break; - - case TIOCSSERIAL: - if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) - return -EFAULT; - - /* - * For now this is ignored. dip sets the ASYNC_[V]HI flags - * but this isn't used by us at all. Maybe someone somewhere - * will need the custom_divisor setting. - */ - - break; - - default: - break; + case TIOCGSERIAL: + memset(&serstruct, 0, sizeof(serstruct)); + serstruct.type = PORT_16654; + serstruct.line = port->serial->minor; + serstruct.port = port->number; + serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + serstruct.xmit_fifo_size = port->bulk_out_size; + serstruct.custom_divisor = 0; + serstruct.baud_base = 460800; + serstruct.close_delay = CLOSING_DELAY; + serstruct.closing_wait = CLOSING_DELAY; + + if (copy_to_user(user_arg, &serstruct, sizeof(serstruct))) + return -EFAULT; + break; + default: + break; } return -ENOIOCTLCMD; } -static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) +static void whiteheat_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { - dbg("%s -port %d", __func__, port->number); - firm_setup_port(port); + firm_setup_port(tty); } - -static void whiteheat_break_ctl(struct usb_serial_port *port, int break_state) { +static void whiteheat_break_ctl(struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = tty->driver_data; firm_set_break(port, break_state); } -static int whiteheat_chars_in_buffer(struct usb_serial_port *port) +static int whiteheat_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); struct list_head *tmp; struct whiteheat_urb_wrap *wrap; @@ -925,13 +950,14 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port) } spin_unlock_irqrestore(&info->lock, flags); - dbg ("%s - returns %d", __func__, chars); + dbg("%s - returns %d", __func__, chars); return chars; } -static void whiteheat_throttle (struct usb_serial_port *port) +static void whiteheat_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); unsigned long flags; @@ -945,8 +971,9 @@ static void whiteheat_throttle (struct usb_serial_port *port) } -static void whiteheat_unthrottle (struct usb_serial_port *port) +static void whiteheat_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); int actually_throttled; unsigned long flags; @@ -993,7 +1020,7 @@ static void command_port_read_callback(struct urb *urb) command_info = usb_get_serial_port_data(command_port); if (!command_info) { - dbg ("%s - command_info is NULL, exiting.", __func__); + dbg("%s - command_info is NULL, exiting.", __func__); return; } if (status) { @@ -1004,7 +1031,8 @@ static void command_port_read_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &command_port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &command_port->dev, + __func__, urb->actual_length, data); if (data[0] == WHITEHEAT_CMD_COMPLETE) { command_info->command_finished = WHITEHEAT_CMD_COMPLETE; @@ -1013,21 +1041,23 @@ static void command_port_read_callback(struct urb *urb) command_info->command_finished = WHITEHEAT_CMD_FAILURE; wake_up(&command_info->wait_command); } else if (data[0] == WHITEHEAT_EVENT) { - /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */ + /* These are unsolicited reports from the firmware, hence no + waiting command to wakeup */ dbg("%s - event received", __func__); } else if (data[0] == WHITEHEAT_GET_DTR_RTS) { - memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1); + memcpy(command_info->result_buffer, &data[1], + urb->actual_length - 1); command_info->command_finished = WHITEHEAT_CMD_COMPLETE; wake_up(&command_info->wait_command); - } else { + } else dbg("%s - bad reply from firmware", __func__); - } - + /* Continue trying to always read */ command_port->read_urb->dev = command_port->serial->dev; result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC); if (result) - dbg("%s - failed resubmitting read urb, error %d", __func__, result); + dbg("%s - failed resubmitting read urb, error %d", + __func__, result); } @@ -1060,7 +1090,8 @@ static void whiteheat_read_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, + __func__, urb->actual_length, data); spin_lock(&info->lock); list_add_tail(&wrap->list, &info->rx_urb_q); @@ -1107,7 +1138,8 @@ static void whiteheat_write_callback(struct urb *urb) /***************************************************************************** * Connect Tech's White Heat firmware interface *****************************************************************************/ -static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize) +static int firm_send_command(struct usb_serial_port *port, __u8 command, + __u8 *data, __u8 datasize) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; @@ -1122,13 +1154,13 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d command_info = usb_get_serial_port_data(command_port); mutex_lock(&command_info->mutex); command_info->command_finished = false; - + transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer; transfer_buffer[0] = command; - memcpy (&transfer_buffer[1], data, datasize); + memcpy(&transfer_buffer[1], data, datasize); command_port->write_urb->transfer_buffer_length = datasize + 1; command_port->write_urb->dev = port->serial->dev; - retval = usb_submit_urb (command_port->write_urb, GFP_NOIO); + retval = usb_submit_urb(command_port->write_urb, GFP_NOIO); if (retval) { dbg("%s - submit urb failed", __func__); goto exit; @@ -1155,51 +1187,57 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) { dbg("%s - command completed.", __func__); switch (command) { - case WHITEHEAT_GET_DTR_RTS: - info = usb_get_serial_port_data(port); - memcpy(&info->mcr, command_info->result_buffer, sizeof(struct whiteheat_dr_info)); + case WHITEHEAT_GET_DTR_RTS: + info = usb_get_serial_port_data(port); + memcpy(&info->mcr, command_info->result_buffer, + sizeof(struct whiteheat_dr_info)); break; } } - exit: mutex_unlock(&command_info->mutex); return retval; } -static int firm_open(struct usb_serial_port *port) { +static int firm_open(struct usb_serial_port *port) +{ struct whiteheat_simple open_command; open_command.port = port->number - port->serial->minor + 1; - return firm_send_command(port, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command)); + return firm_send_command(port, WHITEHEAT_OPEN, + (__u8 *)&open_command, sizeof(open_command)); } -static int firm_close(struct usb_serial_port *port) { +static int firm_close(struct usb_serial_port *port) +{ struct whiteheat_simple close_command; close_command.port = port->number - port->serial->minor + 1; - return firm_send_command(port, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command)); + return firm_send_command(port, WHITEHEAT_CLOSE, + (__u8 *)&close_command, sizeof(close_command)); } -static int firm_setup_port(struct usb_serial_port *port) { +static int firm_setup_port(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; struct whiteheat_port_settings port_settings; - unsigned int cflag = port->tty->termios->c_cflag; + unsigned int cflag = tty->termios->c_cflag; port_settings.port = port->number + 1; /* get the byte size */ switch (cflag & CSIZE) { - case CS5: port_settings.bits = 5; break; - case CS6: port_settings.bits = 6; break; - case CS7: port_settings.bits = 7; break; - default: - case CS8: port_settings.bits = 8; break; + case CS5: port_settings.bits = 5; break; + case CS6: port_settings.bits = 6; break; + case CS7: port_settings.bits = 7; break; + default: + case CS8: port_settings.bits = 8; break; } dbg("%s - data bits = %d", __func__, port_settings.bits); - + /* determine the parity */ if (cflag & PARENB) if (cflag & CMSPAR) @@ -1225,7 +1263,8 @@ static int firm_setup_port(struct usb_serial_port *port) { /* figure out the flow control settings */ if (cflag & CRTSCTS) - port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS); + port_settings.hflow = (WHITEHEAT_HFLOW_CTS | + WHITEHEAT_HFLOW_RTS); else port_settings.hflow = WHITEHEAT_HFLOW_NONE; dbg("%s - hardware flow control = %s %s %s %s", __func__, @@ -1233,81 +1272,95 @@ static int firm_setup_port(struct usb_serial_port *port) { (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "", (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "", (port_settings.hflow & WHITEHEAT_HFLOW_DTR) ? "DTR" : ""); - + /* determine software flow control */ - if (I_IXOFF(port->tty)) + if (I_IXOFF(tty)) port_settings.sflow = WHITEHEAT_SFLOW_RXTX; else port_settings.sflow = WHITEHEAT_SFLOW_NONE; dbg("%s - software flow control = %c", __func__, port_settings.sflow); - - port_settings.xon = START_CHAR(port->tty); - port_settings.xoff = STOP_CHAR(port->tty); - dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff); + + port_settings.xon = START_CHAR(tty); + port_settings.xoff = STOP_CHAR(tty); + dbg("%s - XON = %2x, XOFF = %2x", + __func__, port_settings.xon, port_settings.xoff); /* get the baud rate wanted */ - port_settings.baud = tty_get_baud_rate(port->tty); + port_settings.baud = tty_get_baud_rate(tty); dbg("%s - baud rate = %d", __func__, port_settings.baud); /* fixme: should set validated settings */ - tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud); + tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud); /* handle any settings that aren't specified in the tty structure */ port_settings.lloop = 0; - + /* now send the message to the device */ - return firm_send_command(port, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings)); + return firm_send_command(port, WHITEHEAT_SETUP_PORT, + (__u8 *)&port_settings, sizeof(port_settings)); } -static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) { +static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) +{ struct whiteheat_set_rdb rts_command; rts_command.port = port->number - port->serial->minor + 1; rts_command.state = onoff; - return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&rts_command, sizeof(rts_command)); + return firm_send_command(port, WHITEHEAT_SET_RTS, + (__u8 *)&rts_command, sizeof(rts_command)); } -static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) { +static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) +{ struct whiteheat_set_rdb dtr_command; dtr_command.port = port->number - port->serial->minor + 1; dtr_command.state = onoff; - return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&dtr_command, sizeof(dtr_command)); + return firm_send_command(port, WHITEHEAT_SET_DTR, + (__u8 *)&dtr_command, sizeof(dtr_command)); } -static int firm_set_break(struct usb_serial_port *port, __u8 onoff) { +static int firm_set_break(struct usb_serial_port *port, __u8 onoff) +{ struct whiteheat_set_rdb break_command; break_command.port = port->number - port->serial->minor + 1; break_command.state = onoff; - return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&break_command, sizeof(break_command)); + return firm_send_command(port, WHITEHEAT_SET_BREAK, + (__u8 *)&break_command, sizeof(break_command)); } -static int firm_purge(struct usb_serial_port *port, __u8 rxtx) { +static int firm_purge(struct usb_serial_port *port, __u8 rxtx) +{ struct whiteheat_purge purge_command; purge_command.port = port->number - port->serial->minor + 1; purge_command.what = rxtx; - return firm_send_command(port, WHITEHEAT_PURGE, (__u8 *)&purge_command, sizeof(purge_command)); + return firm_send_command(port, WHITEHEAT_PURGE, + (__u8 *)&purge_command, sizeof(purge_command)); } -static int firm_get_dtr_rts(struct usb_serial_port *port) { +static int firm_get_dtr_rts(struct usb_serial_port *port) +{ struct whiteheat_simple get_dr_command; get_dr_command.port = port->number - port->serial->minor + 1; - return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, (__u8 *)&get_dr_command, sizeof(get_dr_command)); + return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, + (__u8 *)&get_dr_command, sizeof(get_dr_command)); } -static int firm_report_tx_done(struct usb_serial_port *port) { +static int firm_report_tx_done(struct usb_serial_port *port) +{ struct whiteheat_simple close_command; close_command.port = port->number - port->serial->minor + 1; - return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, (__u8 *)&close_command, sizeof(close_command)); + return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, + (__u8 *)&close_command, sizeof(close_command)); } @@ -1319,7 +1372,7 @@ static int start_command_port(struct usb_serial *serial) struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; int retval = 0; - + command_port = serial->port[COMMAND_PORT]; command_info = usb_get_serial_port_data(command_port); mutex_lock(&command_info->mutex); @@ -1330,7 +1383,8 @@ static int start_command_port(struct usb_serial *serial) command_port->read_urb->dev = serial->dev; retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL); if (retval) { - err("%s - failed submitting read urb, error %d", __func__, retval); + err("%s - failed submitting read urb, error %d", + __func__, retval); goto exit; } } @@ -1400,7 +1454,8 @@ static int start_port_read(struct usb_serial_port *port) } -static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head) +static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, + struct list_head *head) { struct whiteheat_urb_wrap *wrap; struct list_head *tmp; @@ -1426,7 +1481,7 @@ static void rx_data_softint(struct work_struct *work) struct whiteheat_private *info = container_of(work, struct whiteheat_private, rx_work); struct usb_serial_port *port = info->port; - struct tty_struct *tty = port->tty; + struct tty_struct *tty = port->port.tty; struct whiteheat_urb_wrap *wrap; struct urb *urb; unsigned long flags; @@ -1449,7 +1504,8 @@ static void rx_data_softint(struct work_struct *work) urb = wrap->urb; if (tty && urb->actual_length) { - int len = tty_buffer_request_room(tty, urb->actual_length); + int len = tty_buffer_request_room(tty, + urb->actual_length); /* This stuff can go away now I suspect */ if (unlikely(len < urb->actual_length)) { spin_lock_irqsave(&info->lock, flags); @@ -1466,7 +1522,8 @@ static void rx_data_softint(struct work_struct *work) urb->dev = port->serial->dev; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - err("%s - failed resubmitting read urb, error %d", __func__, result); + err("%s - failed resubmitting read urb, error %d", + __func__, result); spin_lock_irqsave(&info->lock, flags); list_add(tmp, &info->rx_urbs_free); continue; @@ -1485,7 +1542,7 @@ static void rx_data_softint(struct work_struct *work) /***************************************************************************** * Connect Tech's White Heat module functions *****************************************************************************/ -static int __init whiteheat_init (void) +static int __init whiteheat_init(void) { int retval; retval = usb_serial_register(&whiteheat_fake_device); @@ -1508,19 +1565,19 @@ failed_fake_register: } -static void __exit whiteheat_exit (void) +static void __exit whiteheat_exit(void) { - usb_deregister (&whiteheat_driver); - usb_serial_deregister (&whiteheat_fake_device); - usb_serial_deregister (&whiteheat_device); + usb_deregister(&whiteheat_driver); + usb_serial_deregister(&whiteheat_fake_device); + usb_serial_deregister(&whiteheat_device); } module_init(whiteheat_init); module_exit(whiteheat_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("whiteheat.fw"); diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h index f16079705664..38065df4d2d8 100644 --- a/drivers/usb/serial/whiteheat.h +++ b/drivers/usb/serial/whiteheat.h @@ -2,7 +2,7 @@ * USB ConnectTech WhiteHEAT driver * * Copyright (C) 2002 - * Connect Tech Inc. + * Connect Tech Inc. * * Copyright (C) 1999, 2000 * Greg Kroah-Hartman (greg@kroah.com) @@ -12,7 +12,8 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * */ @@ -30,13 +31,16 @@ #define WHITEHEAT_DUMP 7 /* dump memory */ #define WHITEHEAT_STATUS 8 /* get status */ #define WHITEHEAT_PURGE 9 /* clear the UART fifos */ -#define WHITEHEAT_GET_DTR_RTS 10 /* get the state of DTR and RTS for a port */ -#define WHITEHEAT_GET_HW_INFO 11 /* get EEPROM info and hardware ID */ +#define WHITEHEAT_GET_DTR_RTS 10 /* get the state of DTR and RTS + for a port */ +#define WHITEHEAT_GET_HW_INFO 11 /* get EEPROM info and + hardware ID */ #define WHITEHEAT_REPORT_TX_DONE 12 /* get the next TX done */ #define WHITEHEAT_EVENT 13 /* unsolicited status events */ -#define WHITEHEAT_ECHO 14 /* send data to the indicated IN endpoint */ -#define WHITEHEAT_DO_TEST 15 /* perform the specified test */ -#define WHITEHEAT_CMD_COMPLETE 16 /* reply for certain commands */ +#define WHITEHEAT_ECHO 14 /* send data to the indicated + IN endpoint */ +#define WHITEHEAT_DO_TEST 15 /* perform specified test */ +#define WHITEHEAT_CMD_COMPLETE 16 /* reply for some commands */ #define WHITEHEAT_CMD_FAILURE 17 /* reply for failed commands */ @@ -67,20 +71,28 @@ struct whiteheat_simple { #define WHITEHEAT_PAR_MARK '1' /* mark (force 1) parity */ #define WHITEHEAT_SFLOW_NONE 'n' /* no software flow control */ -#define WHITEHEAT_SFLOW_RX 'r' /* XOFF/ON is sent when RX fills/empties */ -#define WHITEHEAT_SFLOW_TX 't' /* when received XOFF/ON will stop/start TX */ +#define WHITEHEAT_SFLOW_RX 'r' /* XOFF/ON is sent when RX + fills/empties */ +#define WHITEHEAT_SFLOW_TX 't' /* when received XOFF/ON will + stop/start TX */ #define WHITEHEAT_SFLOW_RXTX 'b' /* both SFLOW_RX and SFLOW_TX */ #define WHITEHEAT_HFLOW_NONE 0x00 /* no hardware flow control */ -#define WHITEHEAT_HFLOW_RTS_TOGGLE 0x01 /* RTS is on during transmit, off otherwise */ -#define WHITEHEAT_HFLOW_DTR 0x02 /* DTR is off/on when RX fills/empties */ -#define WHITEHEAT_HFLOW_CTS 0x08 /* when received CTS off/on will stop/start TX */ -#define WHITEHEAT_HFLOW_DSR 0x10 /* when received DSR off/on will stop/start TX */ -#define WHITEHEAT_HFLOW_RTS 0x80 /* RTS is off/on when RX fills/empties */ +#define WHITEHEAT_HFLOW_RTS_TOGGLE 0x01 /* RTS is on during transmit, + off otherwise */ +#define WHITEHEAT_HFLOW_DTR 0x02 /* DTR is off/on when RX + fills/empties */ +#define WHITEHEAT_HFLOW_CTS 0x08 /* when received CTS off/on + will stop/start TX */ +#define WHITEHEAT_HFLOW_DSR 0x10 /* when received DSR off/on + will stop/start TX */ +#define WHITEHEAT_HFLOW_RTS 0x80 /* RTS is off/on when RX + fills/empties */ struct whiteheat_port_settings { __u8 port; /* port number (1 to N) */ - __u32 baud; /* any value 7 - 460800, firmware calculates best fit; arrives little endian */ + __u32 baud; /* any value 7 - 460800, firmware calculates + best fit; arrives little endian */ __u8 bits; /* 5, 6, 7, or 8 */ __u8 stop; /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */ __u8 parity; /* see WHITEHEAT_PAR_* above */ @@ -167,12 +179,14 @@ struct whiteheat_echo { */ #define WHITEHEAT_TEST_UART_RW 0x01 /* read/write uart registers */ #define WHITEHEAT_TEST_UART_INTR 0x02 /* uart interrupt */ -#define WHITEHEAT_TEST_SETUP_CONT 0x03 /* setup for PORT_CONT/PORT_DISCONT */ +#define WHITEHEAT_TEST_SETUP_CONT 0x03 /* setup for + PORT_CONT/PORT_DISCONT */ #define WHITEHEAT_TEST_PORT_CONT 0x04 /* port connect */ #define WHITEHEAT_TEST_PORT_DISCONT 0x05 /* port disconnect */ #define WHITEHEAT_TEST_UART_CLK_START 0x06 /* uart clock test start */ #define WHITEHEAT_TEST_UART_CLK_STOP 0x07 /* uart clock test stop */ -#define WHITEHEAT_TEST_MODEM_FT 0x08 /* modem signals, requires a loopback cable/connector */ +#define WHITEHEAT_TEST_MODEM_FT 0x08 /* modem signals, requires a + loopback cable/connector */ #define WHITEHEAT_TEST_ERASE_EEPROM 0x09 /* erase eeprom */ #define WHITEHEAT_TEST_READ_EEPROM 0x0a /* read eeprom */ #define WHITEHEAT_TEST_PROGRAM_EEPROM 0x0b /* program eeprom */ @@ -198,19 +212,27 @@ struct whiteheat_test { #define WHITEHEAT_EVENT_CONNECT 0x08 /* connect field is valid */ #define WHITEHEAT_FLOW_NONE 0x00 /* no flow control active */ -#define WHITEHEAT_FLOW_HARD_OUT 0x01 /* TX is stopped by CTS (waiting for CTS to go on) */ -#define WHITEHEAT_FLOW_HARD_IN 0x02 /* remote TX is stopped by RTS */ -#define WHITEHEAT_FLOW_SOFT_OUT 0x04 /* TX is stopped by XOFF received (waiting for XON) */ -#define WHITEHEAT_FLOW_SOFT_IN 0x08 /* remote TX is stopped by XOFF transmitted */ +#define WHITEHEAT_FLOW_HARD_OUT 0x01 /* TX is stopped by CTS + (waiting for CTS to go on) */ +#define WHITEHEAT_FLOW_HARD_IN 0x02 /* remote TX is stopped + by RTS */ +#define WHITEHEAT_FLOW_SOFT_OUT 0x04 /* TX is stopped by XOFF + received (waiting for XON) */ +#define WHITEHEAT_FLOW_SOFT_IN 0x08 /* remote TX is stopped by XOFF + transmitted */ #define WHITEHEAT_FLOW_TX_DONE 0x80 /* TX has completed */ struct whiteheat_status_info { __u8 port; /* port number (1 to N) */ - __u8 event; /* indicates what the current event is, see WHITEHEAT_EVENT_* above */ - __u8 modem; /* modem signal status (copy of uart's MSR register) */ + __u8 event; /* indicates what the current event is, + see WHITEHEAT_EVENT_* above */ + __u8 modem; /* modem signal status (copy of uart's + MSR register) */ __u8 error; /* line status (copy of uart's LSR register) */ - __u8 flow; /* flow control state, see WHITEHEAT_FLOW_* above */ - __u8 connect; /* 0 means not connected, non-zero means connected */ + __u8 flow; /* flow control state, see WHITEHEAT_FLOW_* + above */ + __u8 connect; /* 0 means not connected, non-zero means + connected */ }; @@ -256,7 +278,8 @@ struct whiteheat_hw_info { struct whiteheat_event_info { __u8 port; /* port number (1 to N) */ __u8 event; /* see whiteheat_status_info.event */ - __u8 info; /* see whiteheat_status_info.modem, .error, .flow, .connect */ + __u8 info; /* see whiteheat_status_info.modem, .error, + .flow, .connect */ }; @@ -269,7 +292,8 @@ struct whiteheat_event_info { struct whiteheat_test_info { __u8 port; /* port number (1 to N) */ - __u8 test; /* indicates which test this is a response for, see WHITEHEAT_DO_TEST above */ + __u8 test; /* indicates which test this is a response for, + see WHITEHEAT_DO_TEST above */ __u8 status; /* see WHITEHEAT_TEST_* above */ __u8 results[32]; /* test-dependent results */ }; diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 579e9f52053a..17f1ae232919 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -1,7 +1,5 @@ /* Driver for Datafab USB Compact Flash reader * - * $Id: datafab.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $ - * * datafab driver v0.1: * * First release diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c index 01e430654a13..a2b5526c9fa0 100644 --- a/drivers/usb/storage/debug.c +++ b/drivers/usb/storage/debug.c @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * Debugging Functions Source Code File * - * $Id: debug.c,v 1.9 2002/04/22 03:39:43 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h index 77e244a8c376..dbb985d52423 100644 --- a/drivers/usb/storage/debug.h +++ b/drivers/usb/storage/debug.h @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * Debugging Functions Header File * - * $Id: debug.h,v 1.6 2001/01/12 23:51:04 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c index 9a410b5a6e5b..939923471af4 100644 --- a/drivers/usb/storage/dpcm.c +++ b/drivers/usb/storage/dpcm.c @@ -1,7 +1,5 @@ /* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader * - * $Id: dpcm.c,v 1.4 2001/06/11 02:54:25 mdharm Exp $ - * * DPCM driver v0.1: * * First release diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h index 81b464cfcc1e..e7b7b0f120d7 100644 --- a/drivers/usb/storage/dpcm.h +++ b/drivers/usb/storage/dpcm.h @@ -1,7 +1,5 @@ /* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader * - * $Id: dpcm.h,v 1.2 2000/08/25 00:13:51 mdharm Exp $ - * * DPCM driver v0.1: * * First release diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index f5a4e8d6a3b1..7a4d45677227 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -1,7 +1,5 @@ /* Driver for Freecom USB/IDE adaptor * - * $Id: freecom.c,v 1.22 2002/04/22 03:39:43 mdharm Exp $ - * * Freecom v0.1: * * First release diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h index 1b012d62d0a8..20d0fe6ba0c8 100644 --- a/drivers/usb/storage/freecom.h +++ b/drivers/usb/storage/freecom.h @@ -1,7 +1,5 @@ /* Driver for Freecom USB/IDE adaptor * - * $Id: freecom.h,v 1.4 2000/08/29 14:49:15 dlbrown Exp $ - * * Freecom v0.1: * * First release diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 187dd1e01093..4995bb595aef 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -1,7 +1,5 @@ /* Special Initializers for certain USB Mass Storage devices * - * $Id: initializers.c,v 1.2 2000/09/06 22:35:57 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index ad3ffd4236c2..529327fbb06b 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -1,7 +1,5 @@ /* Header file for Special Initializers for certain USB Mass Storage devices * - * $Id: initializers.h,v 1.1 2000/08/29 23:07:02 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 3addcd8f827b..383abf2516a5 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1,7 +1,5 @@ /* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC * - * $Id: isd200.c,v 1.16 2002/04/22 03:39:43 mdharm Exp $ - * * Current development and maintenance: * (C) 2001-2002 Björn Stenberg (bjorn@haxx.se) * @@ -586,7 +584,7 @@ static void isd200_invoke_transport( struct us_data *us, /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ - if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- command was aborted\n"); goto Handle_Abort; } @@ -633,7 +631,7 @@ static void isd200_invoke_transport( struct us_data *us, if (need_auto_sense) { result = isd200_read_regs(us); - if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- auto-sense aborted\n"); goto Handle_Abort; } @@ -663,7 +661,7 @@ static void isd200_invoke_transport( struct us_data *us, srb->result = DID_ABORT << 16; /* permit the reset transfer to take place */ - clear_bit(US_FLIDX_ABORTING, &us->flags); + clear_bit(US_FLIDX_ABORTING, &us->dflags); /* Need reset here */ } diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index 61097cbb1585..df67f13c9e73 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -1,7 +1,5 @@ /* Driver for Lexar "Jumpshot" Compact Flash reader * - * $Id: jumpshot.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $ - * * jumpshot driver v0.1: * * First release diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index b9b8ede61fb3..3b3357e20ea7 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -1,7 +1,5 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: protocol.c,v 1.14 2002/04/22 03:39:43 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h index 8737a36891ca..487056ffb516 100644 --- a/drivers/usb/storage/protocol.h +++ b/drivers/usb/storage/protocol.h @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * Protocol Functions Header File * - * $Id: protocol.h,v 1.4 2001/02/13 07:10:03 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 3fcde9f0fa5f..09779f6a8179 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * SCSI layer glue code * - * $Id: scsiglue.c,v 1.26 2002/04/22 03:39:43 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * @@ -73,7 +71,6 @@ static const char* host_info(struct Scsi_Host *host) static int slave_alloc (struct scsi_device *sdev) { struct us_data *us = host_to_us(sdev->host); - struct usb_host_endpoint *bulk_in_ep; /* * Set the INQUIRY transfer length to 36. We don't use any of @@ -82,16 +79,22 @@ static int slave_alloc (struct scsi_device *sdev) */ sdev->inquiry_len = 36; - /* Scatter-gather buffers (all but the last) must have a length - * divisible by the bulk maxpacket size. Otherwise a data packet - * would end up being short, causing a premature end to the data - * transfer. We'll use the maxpacket value of the bulk-IN pipe - * to set the SCSI device queue's DMA alignment mask. + /* USB has unusual DMA-alignment requirements: Although the + * starting address of each scatter-gather element doesn't matter, + * the length of each element except the last must be divisible + * by the Bulk maxpacket value. There's currently no way to + * express this by block-layer constraints, so we'll cop out + * and simply require addresses to be aligned at 512-byte + * boundaries. This is okay since most block I/O involves + * hardware sectors that are multiples of 512 bytes in length, + * and since host controllers up through USB 2.0 have maxpacket + * values no larger than 512. + * + * But it doesn't suffice for Wireless USB, where Bulk maxpacket + * values can be as large as 2048. To make that work properly + * will require changes to the block layer. */ - bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)]; - blk_queue_update_dma_alignment(sdev->request_queue, - le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1); - /* wMaxPacketSize must be a power of 2 */ + blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); /* * The UFI spec treates the Peripheral Qualifier bits in an @@ -116,10 +119,10 @@ static int slave_configure(struct scsi_device *sdev) * while others have trouble with more than 64K. At this time we * are limiting both to 32K (64 sectores). */ - if (us->flags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) { + if (us->fflags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) { unsigned int max_sectors = 64; - if (us->flags & US_FL_MAX_SECTORS_MIN) + if (us->fflags & US_FL_MAX_SECTORS_MIN) max_sectors = PAGE_CACHE_SIZE >> 9; if (sdev->request_queue->max_sectors > max_sectors) blk_queue_max_sectors(sdev->request_queue, @@ -148,7 +151,7 @@ static int slave_configure(struct scsi_device *sdev) * majority of devices work fine, but a few still can't * handle it. The sd driver will simply assume those * devices are write-enabled. */ - if (us->flags & US_FL_NO_WP_DETECT) + if (us->fflags & US_FL_NO_WP_DETECT) sdev->skip_ms_page_3f = 1; /* A number of devices have problems with MODE SENSE for @@ -158,13 +161,13 @@ static int slave_configure(struct scsi_device *sdev) /* Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver. */ - if (us->flags & US_FL_FIX_CAPACITY) + if (us->fflags & US_FL_FIX_CAPACITY) sdev->fix_capacity = 1; /* A few disks have two indistinguishable version, one of * which reports the correct capacity and the other does not. * The sd driver has to guess which is the case. */ - if (us->flags & US_FL_CAPACITY_HEURISTICS) + if (us->fflags & US_FL_CAPACITY_HEURISTICS) sdev->guess_capacity = 1; /* Some devices report a SCSI revision level above 2 but are @@ -213,7 +216,7 @@ static int slave_configure(struct scsi_device *sdev) /* Some devices choke when they receive a PREVENT-ALLOW MEDIUM * REMOVAL command, so suppress those commands. */ - if (us->flags & US_FL_NOT_LOCKABLE) + if (us->fflags & US_FL_NOT_LOCKABLE) sdev->lockable = 0; /* this is to satisfy the compiler, tho I don't think the @@ -238,7 +241,7 @@ static int queuecommand(struct scsi_cmnd *srb, } /* fail the command if we are disconnecting */ - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { US_DEBUGP("Fail command during disconnect\n"); srb->result = DID_NO_CONNECT << 16; done(srb); @@ -248,7 +251,7 @@ static int queuecommand(struct scsi_cmnd *srb, /* enqueue the command and wake up the control thread */ srb->scsi_done = done; us->srb = srb; - up(&(us->sema)); + complete(&us->cmnd_ready); return 0; } @@ -280,9 +283,9 @@ static int command_abort(struct scsi_cmnd *srb) * with the reset). Note that we must retain the host lock while * calling usb_stor_stop_transport(); otherwise it might interfere * with an auto-reset that begins as soon as we release the lock. */ - set_bit(US_FLIDX_TIMED_OUT, &us->flags); - if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { - set_bit(US_FLIDX_ABORTING, &us->flags); + set_bit(US_FLIDX_TIMED_OUT, &us->dflags); + if (!test_bit(US_FLIDX_RESETTING, &us->dflags)) { + set_bit(US_FLIDX_ABORTING, &us->dflags); usb_stor_stop_transport(us); } scsi_unlock(us_to_host(us)); @@ -329,7 +332,7 @@ void usb_stor_report_device_reset(struct us_data *us) struct Scsi_Host *host = us_to_host(us); scsi_report_device_reset(host, 0, 0); - if (us->flags & US_FL_SCM_MULT_TARG) { + if (us->fflags & US_FL_SCM_MULT_TARG) { for (i = 1; i < host->max_id; ++i) scsi_report_device_reset(host, 0, i); } @@ -400,7 +403,7 @@ static int proc_info (struct Scsi_Host *host, char *buffer, pos += sprintf(pos, " Quirks:"); #define US_FLAG(name, value) \ - if (us->flags & value) pos += sprintf(pos, " " #name); + if (us->fflags & value) pos += sprintf(pos, " " #name); US_DO_ALL_FLAGS #undef US_FLAG diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h index 737e4fa6045f..ffa1cca93d2c 100644 --- a/drivers/usb/storage/scsiglue.h +++ b/drivers/usb/storage/scsiglue.h @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * SCSI Connecting Glue Header File * - * $Id: scsiglue.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 8972b17da843..c5a54b872c24 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1,6 +1,5 @@ /* Driver for SanDisk SDDR-09 SmartMedia reader * - * $Id: sddr09.c,v 1.24 2002/04/22 03:39:43 mdharm Exp $ * (c) 2000, 2001 Robert Baruch (autophile@starband.net) * (c) 2002 Andries Brouwer (aeb@cwi.nl) * Developed with the assistance of: diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h index c03089a9ec38..e50033ad7b19 100644 --- a/drivers/usb/storage/sddr09.h +++ b/drivers/usb/storage/sddr09.h @@ -1,8 +1,6 @@ /* Driver for SanDisk SDDR-09 SmartMedia reader * Header File * - * $Id: sddr09.h,v 1.5 2000/08/25 00:13:51 mdharm Exp $ - * * Current development and maintenance by: * (c) 2000 Robert Baruch (autophile@dol.net) * (c) 2002 Andries Brouwer (aeb@cwi.nl) diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 6d14327c921d..0d8df7577899 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -1,7 +1,5 @@ /* Driver for SanDisk SDDR-55 SmartMedia reader * - * $Id:$ - * * SDDR55 driver v0.1: * * First release diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h index d6bd32f6c9f3..a815a0470c84 100644 --- a/drivers/usb/storage/sddr55.h +++ b/drivers/usb/storage/sddr55.h @@ -1,8 +1,6 @@ /* Driver for SanDisk SDDR-55 SmartMedia reader * Header File * - * $Id:$ - * * Current development and maintenance by: * (c) 2002 Simon Munton * diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 570c1250f6f3..ae6d64810d2a 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1,7 +1,5 @@ /* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable * - * $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $ - * * Current development and maintenance by: * (c) 2000, 2001 Robert Baruch (autophile@starband.net) * (c) 2004, 2005 Daniel Drake <dsd@gentoo.org> diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h index 3ddf143a1dec..d8bfc43e9044 100644 --- a/drivers/usb/storage/shuttle_usbat.h +++ b/drivers/usb/storage/shuttle_usbat.h @@ -1,8 +1,6 @@ /* Driver for SCM Microsystems USB-ATAPI cable * Header File * - * $Id: shuttle_usbat.h,v 1.5 2000/09/17 14:44:52 groovyjava Exp $ - * * Current development and maintenance by: * (c) 2000 Robert Baruch (autophile@dol.net) * (c) 2004, 2005 Daniel Drake <dsd@gentoo.org> diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 6610d2dd1e7f..fcbbfdb7b2b0 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1,7 +1,5 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: transport.c,v 1.47 2002/04/22 03:39:43 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * @@ -75,14 +73,14 @@ * by a separate code path.) * * The abort function (usb_storage_command_abort() in scsiglue.c) first - * sets the machine state and the ABORTING bit in us->flags to prevent + * sets the machine state and the ABORTING bit in us->dflags to prevent * new URBs from being submitted. It then calls usb_stor_stop_transport() - * below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags + * below, which atomically tests-and-clears the URB_ACTIVE bit in us->dflags * to see if the current_urb needs to be stopped. Likewise, the SG_ACTIVE * bit is tested to see if the current_sg scatter-gather request needs to be * stopped. The timeout callback routine does much the same thing. * - * When a disconnect occurs, the DISCONNECTING bit in us->flags is set to + * When a disconnect occurs, the DISCONNECTING bit in us->dflags is set to * prevent new URBs from being submitted, and usb_stor_stop_transport() is * called to stop any ongoing requests. * @@ -127,8 +125,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) long timeleft; int status; - /* don't submit URBs during abort/disconnect processing */ - if (us->flags & ABORTING_OR_DISCONNECTING) + /* don't submit URBs during abort processing */ + if (test_bit(US_FLIDX_ABORTING, &us->dflags)) return -EIO; /* set up data structures for the wakeup system */ @@ -159,13 +157,13 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) /* since the URB has been submitted successfully, it's now okay * to cancel it */ - set_bit(US_FLIDX_URB_ACTIVE, &us->flags); + set_bit(US_FLIDX_URB_ACTIVE, &us->dflags); - /* did an abort/disconnect occur during the submission? */ - if (us->flags & ABORTING_OR_DISCONNECTING) { + /* did an abort occur during the submission? */ + if (test_bit(US_FLIDX_ABORTING, &us->dflags)) { /* cancel the URB, if it hasn't been cancelled already */ - if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { + if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) { US_DEBUGP("-- cancelling URB\n"); usb_unlink_urb(us->current_urb); } @@ -175,7 +173,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) timeleft = wait_for_completion_interruptible_timeout( &urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); - clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); + clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags); if (timeleft <= 0) { US_DEBUGP("%s -- cancelling URB\n", @@ -419,8 +417,8 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, { int result; - /* don't submit s-g requests during abort/disconnect processing */ - if (us->flags & ABORTING_OR_DISCONNECTING) + /* don't submit s-g requests during abort processing */ + if (test_bit(US_FLIDX_ABORTING, &us->dflags)) return USB_STOR_XFER_ERROR; /* initialize the scatter-gather request block */ @@ -435,13 +433,13 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, /* since the block has been initialized successfully, it's now * okay to cancel it */ - set_bit(US_FLIDX_SG_ACTIVE, &us->flags); + set_bit(US_FLIDX_SG_ACTIVE, &us->dflags); - /* did an abort/disconnect occur during the submission? */ - if (us->flags & ABORTING_OR_DISCONNECTING) { + /* did an abort occur during the submission? */ + if (test_bit(US_FLIDX_ABORTING, &us->dflags)) { /* cancel the request, if it hasn't been cancelled already */ - if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) { + if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) { US_DEBUGP("-- cancelling sg request\n"); usb_sg_cancel(&us->current_sg); } @@ -449,7 +447,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, /* wait for the completion of the transfer */ usb_sg_wait(&us->current_sg); - clear_bit(US_FLIDX_SG_ACTIVE, &us->flags); + clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags); result = us->current_sg.status; if (act_len) @@ -530,7 +528,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ - if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- command was aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; @@ -616,7 +614,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* let's clean up right away */ scsi_eh_restore_cmnd(srb, &ses); - if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; @@ -629,7 +627,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) * auto-sense is perfectly valid */ srb->result = DID_ERROR << 16; - if (!(us->flags & US_FL_SCM_MULT_TARG)) + if (!(us->fflags & US_FL_SCM_MULT_TARG)) goto Handle_Errors; return; } @@ -679,8 +677,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* Set the RESETTING bit, and clear the ABORTING bit so that * the reset may proceed. */ scsi_lock(us_to_host(us)); - set_bit(US_FLIDX_RESETTING, &us->flags); - clear_bit(US_FLIDX_ABORTING, &us->flags); + set_bit(US_FLIDX_RESETTING, &us->dflags); + clear_bit(US_FLIDX_ABORTING, &us->dflags); scsi_unlock(us_to_host(us)); /* We must release the device lock because the pre_reset routine @@ -695,7 +693,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) scsi_unlock(us_to_host(us)); us->transport_reset(us); } - clear_bit(US_FLIDX_RESETTING, &us->flags); + clear_bit(US_FLIDX_RESETTING, &us->dflags); } /* Stop the current URB transfer */ @@ -707,13 +705,13 @@ void usb_stor_stop_transport(struct us_data *us) * let's wake it up. The test_and_clear_bit() call * guarantees that if a URB has just been submitted, * it won't be cancelled more than once. */ - if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { + if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) { US_DEBUGP("-- cancelling URB\n"); usb_unlink_urb(us->current_urb); } /* If we are waiting for a scatter-gather operation, cancel it. */ - if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) { + if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) { US_DEBUGP("-- cancelling sg request\n"); usb_sg_cancel(&us->current_sg); } @@ -914,7 +912,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) unsigned int cbwlen = US_BULK_CB_WRAP_LEN; /* Take care of BULK32 devices; set extra byte to 0 */ - if ( unlikely(us->flags & US_FL_BULK32)) { + if (unlikely(us->fflags & US_FL_BULK32)) { cbwlen = 32; us->iobuf[31] = 0; } @@ -925,7 +923,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0; bcb->Tag = ++us->tag; bcb->Lun = srb->device->lun; - if (us->flags & US_FL_SCM_MULT_TARG) + if (us->fflags & US_FL_SCM_MULT_TARG) bcb->Lun |= srb->device->id << 4; bcb->Length = srb->cmd_len; @@ -951,7 +949,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* Some USB-IDE converter chips need a 100us delay between the * command phase and the data phase. Some devices need a little * more than that, probably because of clock rate inaccuracies. */ - if (unlikely(us->flags & US_FL_GO_SLOW)) + if (unlikely(us->fflags & US_FL_GO_SLOW)) udelay(125); if (transfer_length) { @@ -1010,7 +1008,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status); - if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) || + if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) || bcs->Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; @@ -1035,7 +1033,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* try to compute the actual residue, based on how much data * was really transferred and what the device tells us */ if (residue) { - if (!(us->flags & US_FL_IGNORE_RESIDUE)) { + if (!(us->fflags & US_FL_IGNORE_RESIDUE)) { residue = min(residue, transfer_length); scsi_set_resid(srb, max(scsi_get_resid(srb), (int) residue)); @@ -1090,7 +1088,7 @@ static int usb_stor_reset_common(struct us_data *us, int result; int result2; - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { US_DEBUGP("No reset during disconnect\n"); return -EIO; } @@ -1103,12 +1101,12 @@ static int usb_stor_reset_common(struct us_data *us, return result; } - /* Give the device some time to recover from the reset, - * but don't delay disconnect processing. */ - wait_event_interruptible_timeout(us->delay_wait, - test_bit(US_FLIDX_DISCONNECTING, &us->flags), - HZ*6); - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + /* Give the device some time to recover from the reset, + * but don't delay disconnect processing. */ + wait_event_interruptible_timeout(us->delay_wait, + test_bit(US_FLIDX_DISCONNECTING, &us->dflags), + HZ*6); + if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { US_DEBUGP("Reset interrupted by disconnect\n"); return -EIO; } @@ -1170,13 +1168,12 @@ int usb_stor_port_reset(struct us_data *us) US_DEBUGP("unable to lock device for reset: %d\n", result); else { /* Were we disconnected while waiting for the lock? */ - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { result = -EIO; US_DEBUGP("No reset during disconnect\n"); } else { - result = usb_reset_composite_device( - us->pusb_dev, us->pusb_intf); - US_DEBUGP("usb_reset_composite_device returns %d\n", + result = usb_reset_device(us->pusb_dev); + US_DEBUGP("usb_reset_device returns %d\n", result); } if (rc_lock) diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index ada7c2f43f84..e70b88182f0e 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * Transport Functions Header File * - * $Id: transport.h,v 1.18 2002/04/21 02:57:59 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 39a7c11795c4..7ae69f55aa96 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * Unusual Devices File * - * $Id: unusual_devs.h,v 1.32 2002/02/25 02:41:24 mdharm Exp $ - * * Current development and maintenance by: * (c) 2000-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * @@ -1234,6 +1232,17 @@ UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE), +/* Andrew Lunn <andrew@lunn.ch> + * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL + * on LUN 4. + * Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera" +*/ +UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, + "PanDigital", + "Photo Frame", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_NOT_LOCKABLE), + /* Submitted by Jan De Luyck <lkml@kcore.org> */ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, "CITIZEN", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index e268aacb773a..bfea851be985 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -1,7 +1,5 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: usb.c,v 1.75 2002/04/22 03:39:43 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999-2003 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * @@ -312,26 +310,27 @@ static int usb_stor_control_thread(void * __us) for(;;) { US_DEBUGP("*** thread sleeping.\n"); - if(down_interruptible(&us->sema)) + if (wait_for_completion_interruptible(&us->cmnd_ready)) break; - + US_DEBUGP("*** thread awakened.\n"); /* lock the device pointers */ mutex_lock(&(us->dev_mutex)); - /* if the device has disconnected, we are free to exit */ - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { - US_DEBUGP("-- exiting\n"); + /* lock access to the state */ + scsi_lock(host); + + /* When we are called with no command pending, we're done */ + if (us->srb == NULL) { + scsi_unlock(host); mutex_unlock(&us->dev_mutex); + US_DEBUGP("-- exiting\n"); break; } - /* lock access to the state */ - scsi_lock(host); - /* has the command timed out *already* ? */ - if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { us->srb->result = DID_ABORT << 16; goto SkipForAbort; } @@ -350,7 +349,7 @@ static int usb_stor_control_thread(void * __us) * the maximum known LUN */ else if (us->srb->device->id && - !(us->flags & US_FL_SCM_MULT_TARG)) { + !(us->fflags & US_FL_SCM_MULT_TARG)) { US_DEBUGP("Bad target number (%d:%d)\n", us->srb->device->id, us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; @@ -365,7 +364,7 @@ static int usb_stor_control_thread(void * __us) /* Handle those devices which need us to fake * their inquiry data */ else if ((us->srb->cmnd[0] == INQUIRY) && - (us->flags & US_FL_FIX_INQUIRY)) { + (us->fflags & US_FL_FIX_INQUIRY)) { unsigned char data_ptr[36] = { 0x00, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00}; @@ -384,12 +383,8 @@ static int usb_stor_control_thread(void * __us) /* lock access to the state */ scsi_lock(host); - /* did the command already complete because of a disconnect? */ - if (!us->srb) - ; /* nothing to do */ - /* indicate that the command is done */ - else if (us->srb->result != DID_ABORT << 16) { + if (us->srb->result != DID_ABORT << 16) { US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); us->srb->scsi_done(us->srb); @@ -403,12 +398,12 @@ SkipForAbort: * the TIMED_OUT flag, not srb->result == DID_ABORT, because * the timeout might have occurred after the command had * already completed with a different result code. */ - if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { complete(&(us->notify)); /* Allow USB transfers to resume */ - clear_bit(US_FLIDX_ABORTING, &us->flags); - clear_bit(US_FLIDX_TIMED_OUT, &us->flags); + clear_bit(US_FLIDX_ABORTING, &us->dflags); + clear_bit(US_FLIDX_TIMED_OUT, &us->dflags); } /* finished working on this command */ @@ -500,9 +495,9 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? idesc->bInterfaceProtocol : unusual_dev->useTransport; - us->flags = USB_US_ORIG_FLAGS(id->driver_info); + us->fflags = USB_US_ORIG_FLAGS(id->driver_info); - if (us->flags & US_FL_IGNORE_DEVICE) { + if (us->fflags & US_FL_IGNORE_DEVICE) { printk(KERN_INFO USB_STORAGE "device ignored\n"); return -ENODEV; } @@ -512,7 +507,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) * disable it if we're in full-speed */ if (dev->speed != USB_SPEED_HIGH) - us->flags &= ~US_FL_GO_SLOW; + us->fflags &= ~US_FL_GO_SLOW; /* Log a message if a non-generic unusual_dev entry contains an * unnecessary subclass or protocol override. This may stimulate @@ -533,7 +528,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) if (unusual_dev->useTransport != US_PR_DEVICE && us->protocol == idesc->bInterfaceProtocol) msg += 2; - if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE)) + if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE)) printk(KERN_NOTICE USB_STORAGE "This device " "(%04x,%04x,%04x S %02x P %02x)" " has %s in unusual_devs.h (kernel" @@ -663,7 +658,7 @@ static int get_transport(struct us_data *us) US_DEBUGP("Transport: %s\n", us->transport_name); /* fix for single-lun devices */ - if (us->flags & US_FL_SINGLE_LUN) + if (us->fflags & US_FL_SINGLE_LUN) us->max_lun = 0; return 0; } @@ -820,12 +815,11 @@ static void usb_stor_release_resources(struct us_data *us) US_DEBUGP("-- %s\n", __func__); /* Tell the control thread to exit. The SCSI host must - * already have been removed so it won't try to queue - * any more commands. + * already have been removed and the DISCONNECTING flag set + * so that we won't accept any more commands. */ US_DEBUGP("-- sending exit command to thread\n"); - set_bit(US_FLIDX_DISCONNECTING, &us->flags); - up(&us->sema); + complete(&us->cmnd_ready); if (us->ctl_thread) kthread_stop(us->ctl_thread); @@ -859,39 +853,36 @@ static void dissociate_dev(struct us_data *us) usb_set_intfdata(us->pusb_intf, NULL); } -/* First stage of disconnect processing: stop all commands and remove - * the host */ +/* First stage of disconnect processing: stop SCSI scanning, + * remove the host, and stop accepting new commands + */ static void quiesce_and_remove_host(struct us_data *us) { struct Scsi_Host *host = us_to_host(us); - /* Prevent new USB transfers, stop the current command, and - * interrupt a SCSI-scan or device-reset delay */ - scsi_lock(host); - set_bit(US_FLIDX_DISCONNECTING, &us->flags); - scsi_unlock(host); - usb_stor_stop_transport(us); - wake_up(&us->delay_wait); + /* If the device is really gone, cut short reset delays */ + if (us->pusb_dev->state == USB_STATE_NOTATTACHED) + set_bit(US_FLIDX_DISCONNECTING, &us->dflags); - /* queuecommand won't accept any new commands and the control - * thread won't execute a previously-queued command. If there - * is such a command pending, complete it with an error. */ - mutex_lock(&us->dev_mutex); - if (us->srb) { - us->srb->result = DID_NO_CONNECT << 16; - scsi_lock(host); - us->srb->scsi_done(us->srb); - us->srb = NULL; - complete(&us->notify); /* in case of an abort */ - scsi_unlock(host); - } - mutex_unlock(&us->dev_mutex); + /* Prevent SCSI-scanning (if it hasn't started yet) + * and wait for the SCSI-scanning thread to stop. + */ + set_bit(US_FLIDX_DONT_SCAN, &us->dflags); + wake_up(&us->delay_wait); + wait_for_completion(&us->scanning_done); - /* Now we own no commands so it's safe to remove the SCSI host */ + /* Removing the host will perform an orderly shutdown: caches + * synchronized, disks spun down, etc. + */ scsi_remove_host(host); - /* Wait for the SCSI-scanning thread to stop */ - wait_for_completion(&us->scanning_done); + /* Prevent any new commands from being accepted and cut short + * reset delays. + */ + scsi_lock(host); + set_bit(US_FLIDX_DISCONNECTING, &us->dflags); + scsi_unlock(host); + wake_up(&us->delay_wait); } /* Second stage of disconnect processing: deallocate all resources */ @@ -919,16 +910,16 @@ static int usb_stor_scan_thread(void * __us) printk(KERN_DEBUG "usb-storage: waiting for device " "to settle before scanning\n"); wait_event_freezable_timeout(us->delay_wait, - test_bit(US_FLIDX_DISCONNECTING, &us->flags), + test_bit(US_FLIDX_DONT_SCAN, &us->dflags), delay_use * HZ); } /* If the device is still connected, perform the scanning */ - if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) { /* For bulk-only devices, determine the max LUN value */ if (us->protocol == US_PR_BULK && - !(us->flags & US_FL_SINGLE_LUN)) { + !(us->fflags & US_FL_SINGLE_LUN)) { mutex_lock(&us->dev_mutex); us->max_lun = usb_stor_Bulk_max_lun(us); mutex_unlock(&us->dev_mutex); @@ -975,7 +966,7 @@ static int storage_probe(struct usb_interface *intf, us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); - init_MUTEX_LOCKED(&(us->sema)); + init_completion(&us->cmnd_ready); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); init_completion(&us->scanning_done); @@ -1023,6 +1014,7 @@ static int storage_probe(struct usb_interface *intf, if (IS_ERR(th)) { printk(KERN_WARNING USB_STORAGE "Unable to start the device-scanning thread\n"); + complete(&us->scanning_done); quiesce_and_remove_host(us); result = PTR_ERR(th); goto BadDevice; @@ -1065,6 +1057,7 @@ static struct usb_driver usb_storage_driver = { .pre_reset = storage_pre_reset, .post_reset = storage_post_reset, .id_table = storage_usb_ids, + .soft_unbind = 1, }; static int __init usb_stor_init(void) diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 8d87503e2560..a4ad73bd832d 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -1,8 +1,6 @@ /* Driver for USB Mass Storage compliant devices * Main Header File * - * $Id: usb.h,v 1.21 2002/04/21 02:57:59 mdharm Exp $ - * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * @@ -67,16 +65,14 @@ struct us_unusual_dev { }; -/* Dynamic flag definitions: used in set_bit() etc. */ -#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ -#define US_FLIDX_SG_ACTIVE 19 /* 0x00080000 current_sg is in use */ -#define US_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */ -#define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */ -#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ - (1UL << US_FLIDX_DISCONNECTING)) -#define US_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */ -#define US_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI midlayer timed out */ - +/* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */ +#define US_FLIDX_URB_ACTIVE 0 /* current_urb is in use */ +#define US_FLIDX_SG_ACTIVE 1 /* current_sg is in use */ +#define US_FLIDX_ABORTING 2 /* abort is in progress */ +#define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */ +#define US_FLIDX_RESETTING 4 /* device reset in progress */ +#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ +#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */ #define USB_STOR_STRING_LEN 32 @@ -109,7 +105,8 @@ struct us_data { struct usb_device *pusb_dev; /* this usb_device */ struct usb_interface *pusb_intf; /* this interface */ struct us_unusual_dev *unusual_dev; /* device-filter entry */ - unsigned long flags; /* from filter initially */ + unsigned long fflags; /* fixed flags from filter */ + unsigned long dflags; /* dynamic atomic bitflags */ unsigned int send_bulk_pipe; /* cached pipe values */ unsigned int recv_bulk_pipe; unsigned int send_ctrl_pipe; @@ -147,7 +144,7 @@ struct us_data { struct task_struct *ctl_thread; /* the control thread */ /* mutual exclusion and synchronization structures */ - struct semaphore sema; /* to sleep thread on */ + struct completion cmnd_ready; /* to sleep thread on */ struct completion notify; /* thread begin/end */ wait_queue_head_t delay_wait; /* wait during scan, reset */ struct completion scanning_done; /* wait for scan thread */ |