forked from Minki/linux
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (35 commits) usb: add PRODUCT, TYPE to usb-interface events USB: resubmission unusual_devs modification for Nikon D80 usb quirks: Add Canon EOS 5D (PC Connection mode) to the autosuspend blacklist USB: make EHCI initialize properly on PPC SOCs UEAGLE: Remove sysfs files on error case USB: fsl_usb2_udc: fix bug in processing setup requests USB: g_file_storage: fix bug in DMA buffer handling USB: update last_busy field correctly USB: fix DoS in pwc USB video driver USB: allow retry on descriptor fetch errors USB: unkill cxacru atm driver USB: Adding support for HTC Smartphones to ipaq USB: another quirky device USB: quirky mass storage device USB: ohci, fix oddball gcc warning usb-storage: fix bugs in the disconnect pathway usb: typo in usb R8A66597 HCD config USB: accept 1-byte Device Status replies, fixing some b0rken devices USB: blacklist Samsung ML-2010 printer usb-serial: fix oti6858.c segfault in termios handling ...
This commit is contained in:
commit
9e1a3e31cb
@ -1772,6 +1772,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
|
|||||||
if (dev->alt_max_pkt_size == NULL) {
|
if (dev->alt_max_pkt_size == NULL) {
|
||||||
em28xx_errdev("out of memory!\n");
|
em28xx_errdev("out of memory!\n");
|
||||||
em28xx_devused&=~(1<<nr);
|
em28xx_devused&=~(1<<nr);
|
||||||
|
kfree(dev);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void pwc_cleanup(struct pwc_device *pdev)
|
||||||
|
{
|
||||||
|
pwc_remove_sysfs_files(pdev->vdev);
|
||||||
|
video_unregister_device(pdev->vdev);
|
||||||
|
}
|
||||||
|
|
||||||
/* Note that all cleanup is done in the reverse order as in _open */
|
/* Note that all cleanup is done in the reverse order as in _open */
|
||||||
static int pwc_video_close(struct inode *inode, struct file *file)
|
static int pwc_video_close(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct video_device *vdev = file->private_data;
|
struct video_device *vdev = file->private_data;
|
||||||
struct pwc_device *pdev;
|
struct pwc_device *pdev;
|
||||||
int i;
|
int i, hint;
|
||||||
|
|
||||||
PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
|
PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
|
||||||
|
|
||||||
@ -1224,8 +1231,9 @@ static int pwc_video_close(struct inode *inode, struct file *file)
|
|||||||
pwc_isoc_cleanup(pdev);
|
pwc_isoc_cleanup(pdev);
|
||||||
pwc_free_buffers(pdev);
|
pwc_free_buffers(pdev);
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
/* Turn off LEDS and power down camera, but only when not unplugged */
|
/* Turn off LEDS and power down camera, but only when not unplugged */
|
||||||
if (pdev->error_status != EPIPE) {
|
if (!pdev->unplugged) {
|
||||||
/* Turn LEDs off */
|
/* Turn LEDs off */
|
||||||
if (pwc_set_leds(pdev, 0, 0) < 0)
|
if (pwc_set_leds(pdev, 0, 0) < 0)
|
||||||
PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
|
PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
|
||||||
@ -1234,9 +1242,19 @@ static int pwc_video_close(struct inode *inode, struct file *file)
|
|||||||
if (i < 0)
|
if (i < 0)
|
||||||
PWC_ERROR("Failed to power down camera (%d)\n", i);
|
PWC_ERROR("Failed to power down camera (%d)\n", i);
|
||||||
}
|
}
|
||||||
|
pdev->vopen--;
|
||||||
|
PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i);
|
||||||
|
} else {
|
||||||
|
pwc_cleanup(pdev);
|
||||||
|
/* Free memory (don't set pdev to 0 just yet) */
|
||||||
|
kfree(pdev);
|
||||||
|
/* search device_hint[] table if we occupy a slot, by any chance */
|
||||||
|
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
|
||||||
|
if (device_hint[hint].pdev == pdev)
|
||||||
|
device_hint[hint].pdev = NULL;
|
||||||
}
|
}
|
||||||
pdev->vopen--;
|
unlock_kernel();
|
||||||
PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1791,21 +1809,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
|
|||||||
/* Alert waiting processes */
|
/* Alert waiting processes */
|
||||||
wake_up_interruptible(&pdev->frameq);
|
wake_up_interruptible(&pdev->frameq);
|
||||||
/* Wait until device is closed */
|
/* Wait until device is closed */
|
||||||
while (pdev->vopen)
|
if(pdev->vopen) {
|
||||||
schedule();
|
pdev->unplugged = 1;
|
||||||
/* Device is now closed, so we can safely unregister it */
|
} else {
|
||||||
PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
|
/* Device is closed, so we can safely unregister it */
|
||||||
pwc_remove_sysfs_files(pdev->vdev);
|
PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
|
||||||
video_unregister_device(pdev->vdev);
|
pwc_cleanup(pdev);
|
||||||
|
/* Free memory (don't set pdev to 0 just yet) */
|
||||||
/* Free memory (don't set pdev to 0 just yet) */
|
kfree(pdev);
|
||||||
kfree(pdev);
|
|
||||||
|
|
||||||
disconnect_out:
|
disconnect_out:
|
||||||
/* search device_hint[] table if we occupy a slot, by any chance */
|
/* search device_hint[] table if we occupy a slot, by any chance */
|
||||||
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
|
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
|
||||||
if (device_hint[hint].pdev == pdev)
|
if (device_hint[hint].pdev == pdev)
|
||||||
device_hint[hint].pdev = NULL;
|
device_hint[hint].pdev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
}
|
}
|
||||||
|
@ -193,6 +193,7 @@ struct pwc_device
|
|||||||
char vsnapshot; /* snapshot mode */
|
char vsnapshot; /* snapshot mode */
|
||||||
char vsync; /* used by isoc handler */
|
char vsync; /* used by isoc handler */
|
||||||
char vmirror; /* for ToUCaM series */
|
char vmirror; /* for ToUCaM series */
|
||||||
|
char unplugged;
|
||||||
|
|
||||||
int cmd_len;
|
int cmd_len;
|
||||||
unsigned char cmd_buf[13];
|
unsigned char cmd_buf[13];
|
||||||
|
@ -21,6 +21,7 @@ config USB_ARCH_HAS_HCD
|
|||||||
default y if USB_ARCH_HAS_EHCI
|
default y if USB_ARCH_HAS_EHCI
|
||||||
default y if PCMCIA && !M32R # sl811_cs
|
default y if PCMCIA && !M32R # sl811_cs
|
||||||
default y if ARM # SL-811
|
default y if ARM # SL-811
|
||||||
|
default y if SUPERH # r8a66597-hcd
|
||||||
default PCI
|
default PCI
|
||||||
|
|
||||||
# many non-PCI SOC chips embed OHCI
|
# many non-PCI SOC chips embed OHCI
|
||||||
|
@ -456,7 +456,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
|
|||||||
int* actual_length)
|
int* actual_length)
|
||||||
{
|
{
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
int status = urb->status;
|
|
||||||
|
|
||||||
init_timer(&timer);
|
init_timer(&timer);
|
||||||
timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
|
timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
|
||||||
@ -468,7 +467,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
|
|||||||
|
|
||||||
if (actual_length)
|
if (actual_length)
|
||||||
*actual_length = urb->actual_length;
|
*actual_length = urb->actual_length;
|
||||||
return status;
|
return urb->status; /* must read status after completion */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
|
static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
|
||||||
|
@ -1721,9 +1721,12 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
|
|||||||
|
|
||||||
ret = uea_boot(sc);
|
ret = uea_boot(sc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error_rm_grp;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_rm_grp:
|
||||||
|
sysfs_remove_group(&intf->dev.kobj, &attr_grp);
|
||||||
error:
|
error:
|
||||||
kfree(sc);
|
kfree(sc);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -921,6 +921,10 @@ skip_normal_probe:
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Accept probe requests only for the control interface */
|
||||||
|
if (intf != control_interface)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
if (usb_interface_claimed(data_interface)) { /* valid in this context */
|
if (usb_interface_claimed(data_interface)) { /* valid in this context */
|
||||||
dev_dbg(&intf->dev,"The data interface isn't available");
|
dev_dbg(&intf->dev,"The data interface isn't available");
|
||||||
@ -1109,10 +1113,12 @@ static void acm_disconnect(struct usb_interface *intf)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (acm->country_codes){
|
if (acm->country_codes){
|
||||||
device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
|
device_remove_file(&acm->control->dev,
|
||||||
device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
|
&dev_attr_wCountryCodes);
|
||||||
|
device_remove_file(&acm->control->dev,
|
||||||
|
&dev_attr_iCountryCodeRelDate);
|
||||||
}
|
}
|
||||||
device_remove_file(&intf->dev, &dev_attr_bmCapabilities);
|
device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
|
||||||
acm->dev = NULL;
|
acm->dev = NULL;
|
||||||
usb_set_intfdata(acm->control, NULL);
|
usb_set_intfdata(acm->control, NULL);
|
||||||
usb_set_intfdata(acm->data, NULL);
|
usb_set_intfdata(acm->data, NULL);
|
||||||
|
@ -1224,6 +1224,8 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
|
|||||||
udev->auto_pm = 1;
|
udev->auto_pm = 1;
|
||||||
udev->pm_usage_cnt += inc_usage_cnt;
|
udev->pm_usage_cnt += inc_usage_cnt;
|
||||||
WARN_ON(udev->pm_usage_cnt < 0);
|
WARN_ON(udev->pm_usage_cnt < 0);
|
||||||
|
if (inc_usage_cnt)
|
||||||
|
udev->last_busy = jiffies;
|
||||||
if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
|
if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
|
||||||
if (udev->state == USB_STATE_SUSPENDED)
|
if (udev->state == USB_STATE_SUSPENDED)
|
||||||
status = usb_resume_both(udev);
|
status = usb_resume_both(udev);
|
||||||
@ -1232,8 +1234,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
|
|||||||
else if (inc_usage_cnt)
|
else if (inc_usage_cnt)
|
||||||
udev->last_busy = jiffies;
|
udev->last_busy = jiffies;
|
||||||
} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
|
} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
|
||||||
if (inc_usage_cnt)
|
|
||||||
udev->last_busy = jiffies;
|
|
||||||
status = usb_suspend_both(udev, PMSG_SUSPEND);
|
status = usb_suspend_both(udev, PMSG_SUSPEND);
|
||||||
}
|
}
|
||||||
usb_pm_unlock(udev);
|
usb_pm_unlock(udev);
|
||||||
@ -1342,16 +1342,15 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
|
|||||||
else {
|
else {
|
||||||
udev->auto_pm = 1;
|
udev->auto_pm = 1;
|
||||||
intf->pm_usage_cnt += inc_usage_cnt;
|
intf->pm_usage_cnt += inc_usage_cnt;
|
||||||
|
udev->last_busy = jiffies;
|
||||||
if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
|
if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
|
||||||
if (udev->state == USB_STATE_SUSPENDED)
|
if (udev->state == USB_STATE_SUSPENDED)
|
||||||
status = usb_resume_both(udev);
|
status = usb_resume_both(udev);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
intf->pm_usage_cnt -= inc_usage_cnt;
|
intf->pm_usage_cnt -= inc_usage_cnt;
|
||||||
else if (inc_usage_cnt)
|
else
|
||||||
udev->last_busy = jiffies;
|
udev->last_busy = jiffies;
|
||||||
} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
|
} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
|
||||||
if (inc_usage_cnt)
|
|
||||||
udev->last_busy = jiffies;
|
|
||||||
status = usb_suspend_both(udev, PMSG_SUSPEND);
|
status = usb_suspend_both(udev, PMSG_SUSPEND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1644,9 +1644,10 @@ static int finish_port_resume(struct usb_device *udev)
|
|||||||
* and device drivers will know about any resume quirks.
|
* and device drivers will know about any resume quirks.
|
||||||
*/
|
*/
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
devstatus = 0;
|
||||||
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
|
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
|
||||||
if (status >= 0)
|
if (status >= 0)
|
||||||
status = (status == 2 ? 0 : -ENODEV);
|
status = (status > 0 ? 0 : -ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
|
@ -637,12 +637,12 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
|
|||||||
memset(buf,0,size); // Make sure we parse really received data
|
memset(buf,0,size); // Make sure we parse really received data
|
||||||
|
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
/* retry on length 0 or stall; some devices are flakey */
|
/* retry on length 0 or error; some devices are flakey */
|
||||||
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||||
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
|
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
|
||||||
(type << 8) + index, 0, buf, size,
|
(type << 8) + index, 0, buf, size,
|
||||||
USB_CTRL_GET_TIMEOUT);
|
USB_CTRL_GET_TIMEOUT);
|
||||||
if (result == 0 || result == -EPIPE)
|
if (result <= 0 && result != -ETIMEDOUT)
|
||||||
continue;
|
continue;
|
||||||
if (result > 1 && ((u8 *)buf)[1] != type) {
|
if (result > 1 && ((u8 *)buf)[1] != type) {
|
||||||
result = -EPROTO;
|
result = -EPROTO;
|
||||||
@ -1358,6 +1358,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
|
|||||||
usb_dev = interface_to_usbdev(intf);
|
usb_dev = interface_to_usbdev(intf);
|
||||||
alt = intf->cur_altsetting;
|
alt = intf->cur_altsetting;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_DEVICEFS
|
||||||
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
|
buffer, buffer_size, &length,
|
||||||
|
"DEVICE=/proc/bus/usb/%03d/%03d",
|
||||||
|
usb_dev->bus->busnum, usb_dev->devnum))
|
||||||
|
return -ENOMEM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
|
buffer, buffer_size, &length,
|
||||||
|
"PRODUCT=%x/%x/%x",
|
||||||
|
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||||
|
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||||
|
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
|
buffer, buffer_size, &length,
|
||||||
|
"TYPE=%d/%d/%d",
|
||||||
|
usb_dev->descriptor.bDeviceClass,
|
||||||
|
usb_dev->descriptor.bDeviceSubClass,
|
||||||
|
usb_dev->descriptor.bDeviceProtocol))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"INTERFACE=%d/%d/%d",
|
"INTERFACE=%d/%d/%d",
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
static const struct usb_device_id usb_quirk_list[] = {
|
static const struct usb_device_id usb_quirk_list[] = {
|
||||||
/* HP 5300/5370C scanner */
|
/* HP 5300/5370C scanner */
|
||||||
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
|
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
|
||||||
|
/* Hewlett-Packard PhotoSmart 720 / PhotoSmart 935 (storage) */
|
||||||
|
{ USB_DEVICE(0x03f0, 0x4002), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
/* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
|
/* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
|
||||||
{ USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
/* Benq S2W 3300U */
|
/* Benq S2W 3300U */
|
||||||
@ -56,6 +58,8 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||||||
{ USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
/* Seiko Epson Corp.*/
|
/* Seiko Epson Corp.*/
|
||||||
{ USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
|
/* Samsung ML-2010 printer */
|
||||||
|
{ USB_DEVICE(0x04e8, 0x326c), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
/* Samsung ML-2510 Series printer */
|
/* Samsung ML-2510 Series printer */
|
||||||
{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
/* Elsa MicroLink 56k (V.250) */
|
/* Elsa MicroLink 56k (V.250) */
|
||||||
@ -64,12 +68,20 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||||||
{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
/* Agfa Snapscan1212u */
|
/* Agfa Snapscan1212u */
|
||||||
{ USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
|
/* Seagate RSS LLC */
|
||||||
|
{ USB_DEVICE(0x0bc2, 0x3000), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
/* Umax [hex] Astra 3400U */
|
/* Umax [hex] Astra 3400U */
|
||||||
{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
|
|
||||||
/* Philips PSC805 audio device */
|
/* Philips PSC805 audio device */
|
||||||
{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
|
{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||||
|
|
||||||
|
/* Alcor multi-card reader */
|
||||||
|
{ USB_DEVICE(0x058f, 0x6366), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
|
|
||||||
|
/* Canon EOS 5D in PC Connection mode */
|
||||||
|
{ USB_DEVICE(0x04a9, 0x3101), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
|
|
||||||
/* RIM Blackberry */
|
/* RIM Blackberry */
|
||||||
{ USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
{ USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
{ USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
|
||||||
|
@ -34,8 +34,6 @@
|
|||||||
* bypassing some hardware (and driver) issues. UML could help too.
|
* bypassing some hardware (and driver) issues. UML could help too.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUG
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
@ -599,7 +599,6 @@ enum fsg_buffer_state {
|
|||||||
|
|
||||||
struct fsg_buffhd {
|
struct fsg_buffhd {
|
||||||
void *buf;
|
void *buf;
|
||||||
dma_addr_t dma;
|
|
||||||
enum fsg_buffer_state state;
|
enum fsg_buffer_state state;
|
||||||
struct fsg_buffhd *next;
|
struct fsg_buffhd *next;
|
||||||
|
|
||||||
@ -1295,6 +1294,7 @@ static int class_setup_req(struct fsg_dev *fsg,
|
|||||||
struct usb_request *req = fsg->ep0req;
|
struct usb_request *req = fsg->ep0req;
|
||||||
int value = -EOPNOTSUPP;
|
int value = -EOPNOTSUPP;
|
||||||
u16 w_index = le16_to_cpu(ctrl->wIndex);
|
u16 w_index = le16_to_cpu(ctrl->wIndex);
|
||||||
|
u16 w_value = le16_to_cpu(ctrl->wValue);
|
||||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
u16 w_length = le16_to_cpu(ctrl->wLength);
|
||||||
|
|
||||||
if (!fsg->config)
|
if (!fsg->config)
|
||||||
@ -1308,7 +1308,7 @@ static int class_setup_req(struct fsg_dev *fsg,
|
|||||||
if (ctrl->bRequestType != (USB_DIR_OUT |
|
if (ctrl->bRequestType != (USB_DIR_OUT |
|
||||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
|
||||||
break;
|
break;
|
||||||
if (w_index != 0) {
|
if (w_index != 0 || w_value != 0) {
|
||||||
value = -EDOM;
|
value = -EDOM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1324,7 +1324,7 @@ static int class_setup_req(struct fsg_dev *fsg,
|
|||||||
if (ctrl->bRequestType != (USB_DIR_IN |
|
if (ctrl->bRequestType != (USB_DIR_IN |
|
||||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
|
||||||
break;
|
break;
|
||||||
if (w_index != 0) {
|
if (w_index != 0 || w_value != 0) {
|
||||||
value = -EDOM;
|
value = -EDOM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1343,7 +1343,7 @@ static int class_setup_req(struct fsg_dev *fsg,
|
|||||||
if (ctrl->bRequestType != (USB_DIR_OUT |
|
if (ctrl->bRequestType != (USB_DIR_OUT |
|
||||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
|
||||||
break;
|
break;
|
||||||
if (w_index != 0) {
|
if (w_index != 0 || w_value != 0) {
|
||||||
value = -EDOM;
|
value = -EDOM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2611,7 +2611,6 @@ static int send_status(struct fsg_dev *fsg)
|
|||||||
|
|
||||||
fsg->intr_buffhd = bh; // Point to the right buffhd
|
fsg->intr_buffhd = bh; // Point to the right buffhd
|
||||||
fsg->intreq->buf = bh->inreq->buf;
|
fsg->intreq->buf = bh->inreq->buf;
|
||||||
fsg->intreq->dma = bh->inreq->dma;
|
|
||||||
fsg->intreq->context = bh;
|
fsg->intreq->context = bh;
|
||||||
start_transfer(fsg, fsg->intr_in, fsg->intreq,
|
start_transfer(fsg, fsg->intr_in, fsg->intreq,
|
||||||
&fsg->intreq_busy, &bh->state);
|
&fsg->intreq_busy, &bh->state);
|
||||||
@ -3200,7 +3199,6 @@ reset:
|
|||||||
if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
|
if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
|
||||||
goto reset;
|
goto reset;
|
||||||
bh->inreq->buf = bh->outreq->buf = bh->buf;
|
bh->inreq->buf = bh->outreq->buf = bh->buf;
|
||||||
bh->inreq->dma = bh->outreq->dma = bh->dma;
|
|
||||||
bh->inreq->context = bh->outreq->context = bh;
|
bh->inreq->context = bh->outreq->context = bh;
|
||||||
bh->inreq->complete = bulk_in_complete;
|
bh->inreq->complete = bulk_in_complete;
|
||||||
bh->outreq->complete = bulk_out_complete;
|
bh->outreq->complete = bulk_out_complete;
|
||||||
|
@ -1277,31 +1277,32 @@ static void setup_received_irq(struct fsl_udc *udc,
|
|||||||
|
|
||||||
udc_reset_ep_queue(udc, 0);
|
udc_reset_ep_queue(udc, 0);
|
||||||
|
|
||||||
|
/* We process some stardard setup requests here */
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
/* Request that need Data+Status phase from udc */
|
|
||||||
case USB_REQ_GET_STATUS:
|
case USB_REQ_GET_STATUS:
|
||||||
if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_STANDARD))
|
/* Data+Status phase from udc */
|
||||||
|
if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
|
||||||
!= (USB_DIR_IN | USB_TYPE_STANDARD))
|
!= (USB_DIR_IN | USB_TYPE_STANDARD))
|
||||||
break;
|
break;
|
||||||
ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
|
ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
|
||||||
break;
|
return;
|
||||||
|
|
||||||
/* Requests that need Status phase from udc */
|
|
||||||
case USB_REQ_SET_ADDRESS:
|
case USB_REQ_SET_ADDRESS:
|
||||||
|
/* Status phase from udc */
|
||||||
if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
|
if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
|
||||||
| USB_RECIP_DEVICE))
|
| USB_RECIP_DEVICE))
|
||||||
break;
|
break;
|
||||||
ch9setaddress(udc, wValue, wIndex, wLength);
|
ch9setaddress(udc, wValue, wIndex, wLength);
|
||||||
break;
|
return;
|
||||||
|
|
||||||
/* Handled by udc, no data, status by udc */
|
|
||||||
case USB_REQ_CLEAR_FEATURE:
|
case USB_REQ_CLEAR_FEATURE:
|
||||||
case USB_REQ_SET_FEATURE:
|
case USB_REQ_SET_FEATURE:
|
||||||
{ /* status transaction */
|
/* Status phase from udc */
|
||||||
|
{
|
||||||
int rc = -EOPNOTSUPP;
|
int rc = -EOPNOTSUPP;
|
||||||
|
|
||||||
if ((setup->bRequestType & USB_RECIP_MASK)
|
if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
|
||||||
== USB_RECIP_ENDPOINT) {
|
== (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
|
||||||
int pipe = get_pipe_by_windex(wIndex);
|
int pipe = get_pipe_by_windex(wIndex);
|
||||||
struct fsl_ep *ep;
|
struct fsl_ep *ep;
|
||||||
|
|
||||||
@ -1315,8 +1316,9 @@ static void setup_received_irq(struct fsl_udc *udc,
|
|||||||
? 1 : 0);
|
? 1 : 0);
|
||||||
spin_lock(&udc->lock);
|
spin_lock(&udc->lock);
|
||||||
|
|
||||||
} else if ((setup->bRequestType & USB_RECIP_MASK)
|
} else if ((setup->bRequestType & (USB_RECIP_MASK
|
||||||
== USB_RECIP_DEVICE) {
|
| USB_TYPE_MASK)) == (USB_RECIP_DEVICE
|
||||||
|
| USB_TYPE_STANDARD)) {
|
||||||
/* Note: The driver has not include OTG support yet.
|
/* Note: The driver has not include OTG support yet.
|
||||||
* This will be set when OTG support is added */
|
* This will be set when OTG support is added */
|
||||||
if (!udc->gadget.is_otg)
|
if (!udc->gadget.is_otg)
|
||||||
@ -1329,38 +1331,41 @@ static void setup_received_irq(struct fsl_udc *udc,
|
|||||||
USB_DEVICE_A_ALT_HNP_SUPPORT)
|
USB_DEVICE_A_ALT_HNP_SUPPORT)
|
||||||
udc->gadget.a_alt_hnp_support = 1;
|
udc->gadget.a_alt_hnp_support = 1;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
if (ep0_prime_status(udc, EP_DIR_IN))
|
if (ep0_prime_status(udc, EP_DIR_IN))
|
||||||
ep0stall(udc);
|
ep0stall(udc);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Requests handled by gadget */
|
|
||||||
default:
|
|
||||||
if (wLength) {
|
|
||||||
/* Data phase from gadget, status phase from udc */
|
|
||||||
udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
|
|
||||||
? USB_DIR_IN : USB_DIR_OUT;
|
|
||||||
spin_unlock(&udc->lock);
|
|
||||||
if (udc->driver->setup(&udc->gadget,
|
|
||||||
&udc->local_setup_buff) < 0)
|
|
||||||
ep0stall(udc);
|
|
||||||
spin_lock(&udc->lock);
|
|
||||||
udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
|
|
||||||
? DATA_STATE_XMIT : DATA_STATE_RECV;
|
|
||||||
|
|
||||||
} else {
|
/* Requests handled by gadget */
|
||||||
/* No data phase, IN status from gadget */
|
if (wLength) {
|
||||||
udc->ep0_dir = USB_DIR_IN;
|
/* Data phase from gadget, status phase from udc */
|
||||||
spin_unlock(&udc->lock);
|
udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
|
||||||
if (udc->driver->setup(&udc->gadget,
|
? USB_DIR_IN : USB_DIR_OUT;
|
||||||
&udc->local_setup_buff) < 0)
|
spin_unlock(&udc->lock);
|
||||||
ep0stall(udc);
|
if (udc->driver->setup(&udc->gadget,
|
||||||
spin_lock(&udc->lock);
|
&udc->local_setup_buff) < 0)
|
||||||
udc->ep0_state = WAIT_FOR_OUT_STATUS;
|
ep0stall(udc);
|
||||||
}
|
spin_lock(&udc->lock);
|
||||||
break;
|
udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
|
||||||
|
? DATA_STATE_XMIT : DATA_STATE_RECV;
|
||||||
|
} else {
|
||||||
|
/* No data phase, IN status from gadget */
|
||||||
|
udc->ep0_dir = USB_DIR_IN;
|
||||||
|
spin_unlock(&udc->lock);
|
||||||
|
if (udc->driver->setup(&udc->gadget,
|
||||||
|
&udc->local_setup_buff) < 0)
|
||||||
|
ep0stall(udc);
|
||||||
|
spin_lock(&udc->lock);
|
||||||
|
udc->ep0_state = WAIT_FOR_OUT_STATUS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -967,7 +967,7 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
|
|||||||
udc = container_of(_gadget, struct pxa2xx_udc, gadget);
|
udc = container_of(_gadget, struct pxa2xx_udc, gadget);
|
||||||
|
|
||||||
/* not all boards support pullup control */
|
/* not all boards support pullup control */
|
||||||
if (!udc->mach->udc_command)
|
if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
is_active = (is_active != 0);
|
is_active = (is_active != 0);
|
||||||
@ -2309,7 +2309,7 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
|
|||||||
{
|
{
|
||||||
struct pxa2xx_udc *udc = platform_get_drvdata(dev);
|
struct pxa2xx_udc *udc = platform_get_drvdata(dev);
|
||||||
|
|
||||||
if (!udc->mach->udc_command)
|
if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
|
||||||
WARN("USB host won't detect disconnect!\n");
|
WARN("USB host won't detect disconnect!\n");
|
||||||
pullup(udc, 0);
|
pullup(udc, 0);
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ config USB_SL811_CS
|
|||||||
module will be called "sl811_cs".
|
module will be called "sl811_cs".
|
||||||
|
|
||||||
config USB_R8A66597_HCD
|
config USB_R8A66597_HCD
|
||||||
tristate "R8A66597 HCD suppoort"
|
tristate "R8A66597 HCD support"
|
||||||
depends on USB
|
depends on USB
|
||||||
help
|
help
|
||||||
The R8A66597 is a USB 2.0 host and peripheral controller.
|
The R8A66597 is a USB 2.0 host and peripheral controller.
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* EHCI HCD (Host Controller Driver) for USB.
|
* EHCI HCD (Host Controller Driver) for USB.
|
||||||
*
|
*
|
||||||
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
|
|
||||||
*
|
|
||||||
* Bus Glue for AMD Alchemy Au1xxx
|
* Bus Glue for AMD Alchemy Au1xxx
|
||||||
*
|
*
|
||||||
* Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
|
* Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
|
||||||
@ -196,6 +194,9 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* basic lifecycle operations
|
* basic lifecycle operations
|
||||||
|
*
|
||||||
|
* FIXME -- ehci_init() doesn't do enough here.
|
||||||
|
* See ehci-ppc-soc for a complete implementation.
|
||||||
*/
|
*/
|
||||||
.reset = ehci_init,
|
.reset = ehci_init,
|
||||||
.start = ehci_run,
|
.start = ehci_run,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Bus Glue for PPC On-Chip EHCI driver
|
* Bus Glue for PPC On-Chip EHCI driver
|
||||||
* Tested on AMCC 440EPx
|
* Tested on AMCC 440EPx
|
||||||
*
|
*
|
||||||
* Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net>
|
* Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com>
|
||||||
*
|
*
|
||||||
* This file is licenced under the GPL.
|
* This file is licenced under the GPL.
|
||||||
*/
|
*/
|
||||||
@ -15,6 +15,24 @@
|
|||||||
|
|
||||||
extern int usb_disabled(void);
|
extern int usb_disabled(void);
|
||||||
|
|
||||||
|
/* called during probe() after chip reset completes */
|
||||||
|
static int ehci_ppc_soc_setup(struct usb_hcd *hcd)
|
||||||
|
{
|
||||||
|
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = ehci_halt(ehci);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = ehci_init(hcd);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
ehci->sbrn = 0x20;
|
||||||
|
return ehci_reset(ehci);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
|
* usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
|
||||||
* Context: !in_interrupt()
|
* Context: !in_interrupt()
|
||||||
@ -120,7 +138,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
|
|||||||
/*
|
/*
|
||||||
* basic lifecycle operations
|
* basic lifecycle operations
|
||||||
*/
|
*/
|
||||||
.reset = ehci_init,
|
.reset = ehci_ppc_soc_setup,
|
||||||
.start = ehci_run,
|
.start = ehci_run,
|
||||||
.stop = ehci_stop,
|
.stop = ehci_stop,
|
||||||
.shutdown = ehci_shutdown,
|
.shutdown = ehci_shutdown,
|
||||||
|
@ -74,7 +74,7 @@ urb_print (struct urb * urb, char * str, int small)
|
|||||||
|
|
||||||
#define ohci_dbg_sw(ohci, next, size, format, arg...) \
|
#define ohci_dbg_sw(ohci, next, size, format, arg...) \
|
||||||
do { \
|
do { \
|
||||||
if (next) { \
|
if (next != NULL) { \
|
||||||
unsigned s_len; \
|
unsigned s_len; \
|
||||||
s_len = scnprintf (*next, *size, format, ## arg ); \
|
s_len = scnprintf (*next, *size, format, ## arg ); \
|
||||||
*size -= s_len; *next += s_len; \
|
*size -= s_len; *next += s_len; \
|
||||||
|
@ -2208,8 +2208,6 @@ static int __init r8a66597_probe(struct platform_device *pdev)
|
|||||||
clean_up:
|
clean_up:
|
||||||
if (reg)
|
if (reg)
|
||||||
iounmap(reg);
|
iounmap(reg);
|
||||||
if (res)
|
|
||||||
release_mem_region(res->start, 1);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1520,12 +1520,15 @@ static void u132_hcd_endp_work_scheduler(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
|
||||||
static void port_power(struct u132 *u132, int pn, int is_on)
|
static void port_power(struct u132 *u132, int pn, int is_on)
|
||||||
{
|
{
|
||||||
u132->port[pn].power = is_on;
|
u132->port[pn].power = is_on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void u132_power(struct u132 *u132, int is_on)
|
static void u132_power(struct u132 *u132, int is_on)
|
||||||
{
|
{
|
||||||
struct usb_hcd *hcd = u132_to_hcd(u132)
|
struct usb_hcd *hcd = u132_to_hcd(u132)
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
static struct usb_device_id id_table [] = {
|
static struct usb_device_id id_table [] = {
|
||||||
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
|
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
|
||||||
{ USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
|
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(usb, id_table);
|
MODULE_DEVICE_TABLE(usb, id_table);
|
||||||
|
@ -383,6 +383,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
|
|||||||
}
|
}
|
||||||
|
|
||||||
baud = tty_get_baud_rate(port->tty);
|
baud = tty_get_baud_rate(port->tty);
|
||||||
|
if (baud == 0) {
|
||||||
|
dbg("%s - tty_get_baud_rate says 0 baud", __FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
urb_value = BELKIN_SA_BAUD(baud);
|
urb_value = BELKIN_SA_BAUD(baud);
|
||||||
/* Clip to maximum speed */
|
/* Clip to maximum speed */
|
||||||
if (urb_value == 0)
|
if (urb_value == 0)
|
||||||
|
@ -538,6 +538,8 @@ static struct usb_device_id id_table_combined [] = {
|
|||||||
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
|
||||||
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
|
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
|
||||||
|
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
|
||||||
|
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
|
||||||
|
@ -430,6 +430,9 @@
|
|||||||
*/
|
*/
|
||||||
#define EVOLUTION_VID 0xDEEE /* Vendor ID */
|
#define EVOLUTION_VID 0xDEEE /* Vendor ID */
|
||||||
#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */
|
#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */
|
||||||
|
#define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/
|
||||||
|
#define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/
|
||||||
|
#define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */
|
||||||
|
|
||||||
/* Pyramid Computer GmbH */
|
/* Pyramid Computer GmbH */
|
||||||
#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */
|
#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Garmin GPS driver
|
* Garmin GPS driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net
|
* Copyright (C) 2006,2007 Hermann Kneissel herkne@users.sourceforge.net
|
||||||
*
|
*
|
||||||
* The latest version of the driver can be found at
|
* The latest version of the driver can be found at
|
||||||
* http://sourceforge.net/projects/garmin-gps/
|
* http://sourceforge.net/projects/garmin-gps/
|
||||||
@ -34,6 +34,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <asm/atomic.h>
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/usb/serial.h>
|
#include <linux/usb/serial.h>
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ static int debug = 0;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 28
|
#define VERSION_MINOR 31
|
||||||
|
|
||||||
#define _STR(s) #s
|
#define _STR(s) #s
|
||||||
#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
|
#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
|
||||||
@ -141,6 +142,8 @@ struct garmin_data {
|
|||||||
__u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */
|
__u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */
|
||||||
__u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */
|
__u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */
|
||||||
__u8 privpkt[4*6];
|
__u8 privpkt[4*6];
|
||||||
|
atomic_t req_count;
|
||||||
|
atomic_t resp_count;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
struct list_head pktlist;
|
struct list_head pktlist;
|
||||||
};
|
};
|
||||||
@ -171,8 +174,6 @@ struct garmin_data {
|
|||||||
#define CLEAR_HALT_REQUIRED 0x0001
|
#define CLEAR_HALT_REQUIRED 0x0001
|
||||||
|
|
||||||
#define FLAGS_QUEUING 0x0100
|
#define FLAGS_QUEUING 0x0100
|
||||||
#define FLAGS_APP_RESP_SEEN 0x0200
|
|
||||||
#define FLAGS_APP_REQ_SEEN 0x0400
|
|
||||||
#define FLAGS_DROP_DATA 0x0800
|
#define FLAGS_DROP_DATA 0x0800
|
||||||
|
|
||||||
#define FLAGS_GSP_SKIP 0x1000
|
#define FLAGS_GSP_SKIP 0x1000
|
||||||
@ -186,7 +187,8 @@ struct garmin_data {
|
|||||||
/* function prototypes */
|
/* 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,
|
static int garmin_write_bulk(struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count,
|
||||||
|
int dismiss_ack);
|
||||||
|
|
||||||
/* some special packets to be send or received */
|
/* some special packets to be send or received */
|
||||||
static unsigned char const GARMIN_START_SESSION_REQ[]
|
static unsigned char const GARMIN_START_SESSION_REQ[]
|
||||||
@ -233,9 +235,7 @@ 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 ((garmin_data_p->flags
|
return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count);
|
||||||
& (FLAGS_APP_REQ_SEEN|FLAGS_APP_RESP_SEEN))
|
|
||||||
== FLAGS_APP_REQ_SEEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -463,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
|
|||||||
usbdata[2] = __cpu_to_le32(size);
|
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);
|
GARMIN_PKTHDR_LENGTH+size, 0);
|
||||||
|
|
||||||
/* if this was an abort-transfer command, flush all
|
/* if this was an abort-transfer command, flush all
|
||||||
queued data. */
|
queued data. */
|
||||||
@ -818,7 +818,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
|
|||||||
if (garmin_data_p->insize >= len) {
|
if (garmin_data_p->insize >= len) {
|
||||||
garmin_write_bulk (garmin_data_p->port,
|
garmin_write_bulk (garmin_data_p->port,
|
||||||
garmin_data_p->inbuffer,
|
garmin_data_p->inbuffer,
|
||||||
len);
|
len, 0);
|
||||||
garmin_data_p->insize = 0;
|
garmin_data_p->insize = 0;
|
||||||
|
|
||||||
/* if this was an abort-transfer command,
|
/* if this was an abort-transfer command,
|
||||||
@ -893,10 +893,11 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
|
|||||||
|
|
||||||
struct usb_serial_port *port = garmin_data_p->port;
|
struct usb_serial_port *port = garmin_data_p->port;
|
||||||
|
|
||||||
if (port != NULL && garmin_data_p->flags & FLAGS_APP_RESP_SEEN) {
|
if (port != NULL && atomic_read(&garmin_data_p->resp_count)) {
|
||||||
/* send a terminate command */
|
/* send a terminate command */
|
||||||
status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
|
status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
|
||||||
sizeof(GARMIN_STOP_TRANSFER_REQ));
|
sizeof(GARMIN_STOP_TRANSFER_REQ),
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* flush all queued data */
|
/* flush all queued data */
|
||||||
@ -939,7 +940,8 @@ static int garmin_init_session(struct usb_serial_port *port)
|
|||||||
dbg("%s - starting session ...", __FUNCTION__);
|
dbg("%s - starting session ...", __FUNCTION__);
|
||||||
garmin_data_p->state = STATE_ACTIVE;
|
garmin_data_p->state = STATE_ACTIVE;
|
||||||
status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
|
status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
|
||||||
sizeof(GARMIN_START_SESSION_REQ));
|
sizeof(GARMIN_START_SESSION_REQ),
|
||||||
|
0);
|
||||||
|
|
||||||
if (status >= 0) {
|
if (status >= 0) {
|
||||||
|
|
||||||
@ -950,7 +952,8 @@ static int garmin_init_session(struct usb_serial_port *port)
|
|||||||
/* not needed, but the win32 driver does it too ... */
|
/* not needed, but the win32 driver does it too ... */
|
||||||
status = garmin_write_bulk(port,
|
status = garmin_write_bulk(port,
|
||||||
GARMIN_START_SESSION_REQ2,
|
GARMIN_START_SESSION_REQ2,
|
||||||
sizeof(GARMIN_START_SESSION_REQ2));
|
sizeof(GARMIN_START_SESSION_REQ2),
|
||||||
|
0);
|
||||||
if (status >= 0) {
|
if (status >= 0) {
|
||||||
status = 0;
|
status = 0;
|
||||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
@ -987,6 +990,8 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
|
|||||||
garmin_data_p->mode = initial_mode;
|
garmin_data_p->mode = initial_mode;
|
||||||
garmin_data_p->count = 0;
|
garmin_data_p->count = 0;
|
||||||
garmin_data_p->flags = 0;
|
garmin_data_p->flags = 0;
|
||||||
|
atomic_set(&garmin_data_p->req_count, 0);
|
||||||
|
atomic_set(&garmin_data_p->resp_count, 0);
|
||||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
|
||||||
/* shutdown any bulk reads that might be going on */
|
/* shutdown any bulk reads that might be going on */
|
||||||
@ -1035,28 +1040,39 @@ static void garmin_write_bulk_callback (struct urb *urb)
|
|||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||||
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
|
||||||
int status = urb->status;
|
int status = urb->status;
|
||||||
|
|
||||||
|
if (port) {
|
||||||
|
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
dbg("%s - port %d", __FUNCTION__, 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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
dbg("%s - nonzero write bulk status received: %d",
|
||||||
|
__FUNCTION__, urb->status);
|
||||||
|
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
||||||
|
garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
|
||||||
|
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_serial_port_softint(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* 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", __FUNCTION__, port->number);
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
dbg("%s - nonzero write bulk status received: %d",
|
|
||||||
__FUNCTION__, status);
|
|
||||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
|
||||||
garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
|
|
||||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_serial_port_softint(port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
const unsigned char *buf, int count,
|
||||||
|
int dismiss_ack)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
@ -1093,13 +1109,12 @@ static int garmin_write_bulk (struct usb_serial_port *port,
|
|||||||
usb_sndbulkpipe (serial->dev,
|
usb_sndbulkpipe (serial->dev,
|
||||||
port->bulk_out_endpointAddress),
|
port->bulk_out_endpointAddress),
|
||||||
buffer, count,
|
buffer, count,
|
||||||
garmin_write_bulk_callback, port);
|
garmin_write_bulk_callback,
|
||||||
|
dismiss_ack ? NULL : port);
|
||||||
urb->transfer_flags |= URB_ZERO_PACKET;
|
urb->transfer_flags |= URB_ZERO_PACKET;
|
||||||
|
|
||||||
if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
|
if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
|
||||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
atomic_inc(&garmin_data_p->req_count);
|
||||||
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
|
||||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
|
||||||
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
|
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
|
||||||
pkt_clear(garmin_data_p);
|
pkt_clear(garmin_data_p);
|
||||||
garmin_data_p->state = STATE_GSP_WAIT_DATA;
|
garmin_data_p->state = STATE_GSP_WAIT_DATA;
|
||||||
@ -1114,13 +1129,6 @@ static int garmin_write_bulk (struct usb_serial_port *port,
|
|||||||
"failed with status = %d\n",
|
"failed with status = %d\n",
|
||||||
__FUNCTION__, status);
|
__FUNCTION__, status);
|
||||||
count = status;
|
count = status;
|
||||||
} else {
|
|
||||||
|
|
||||||
if (GARMIN_LAYERID_APPL == getLayerId(buffer)
|
|
||||||
&& (garmin_data_p->mode == MODE_GARMIN_SERIAL)) {
|
|
||||||
|
|
||||||
gsp_send_ack(garmin_data_p, buffer[4]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we are done with this urb, so let the host driver
|
/* we are done with this urb, so let the host driver
|
||||||
@ -1135,7 +1143,6 @@ static int garmin_write_bulk (struct usb_serial_port *port,
|
|||||||
static int garmin_write (struct usb_serial_port *port,
|
static int garmin_write (struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count)
|
const unsigned char *buf, int count)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
int pktid, pktsiz, len;
|
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;
|
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
|
||||||
@ -1186,9 +1193,7 @@ static int garmin_write (struct usb_serial_port *port,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PRIV_PKTID_RESET_REQ:
|
case PRIV_PKTID_RESET_REQ:
|
||||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
atomic_inc(&garmin_data_p->req_count);
|
||||||
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
|
|
||||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRIV_PKTID_SET_DEF_MODE:
|
case PRIV_PKTID_SET_DEF_MODE:
|
||||||
@ -1241,8 +1246,6 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
|
|||||||
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)
|
unsigned char *data, unsigned data_length)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
|
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
|
||||||
/* abort-transfer cmd is actice */
|
/* abort-transfer cmd is actice */
|
||||||
dbg("%s - pkt dropped", __FUNCTION__);
|
dbg("%s - pkt dropped", __FUNCTION__);
|
||||||
@ -1254,9 +1257,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
|
|||||||
the device */
|
the device */
|
||||||
if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
|
if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
|
||||||
sizeof(GARMIN_APP_LAYER_REPLY))) {
|
sizeof(GARMIN_APP_LAYER_REPLY))) {
|
||||||
spin_lock_irqsave(&garmin_data_p->lock, flags);
|
atomic_inc(&garmin_data_p->resp_count);
|
||||||
garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
|
|
||||||
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if throttling is active or postprecessing is required
|
/* if throttling is active or postprecessing is required
|
||||||
|
@ -545,6 +545,7 @@ static struct usb_device_id ipaq_id_table [] = {
|
|||||||
{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
|
{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
|
||||||
{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
|
{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
|
||||||
{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
|
{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
|
||||||
|
{ USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ static int option_send_setup(struct usb_serial_port *port);
|
|||||||
#define HUAWEI_PRODUCT_E220 0x1003
|
#define HUAWEI_PRODUCT_E220 0x1003
|
||||||
|
|
||||||
#define NOVATELWIRELESS_VENDOR_ID 0x1410
|
#define NOVATELWIRELESS_VENDOR_ID 0x1410
|
||||||
|
#define DELL_VENDOR_ID 0x413C
|
||||||
|
|
||||||
#define ANYDATA_VENDOR_ID 0x16d5
|
#define ANYDATA_VENDOR_ID 0x16d5
|
||||||
#define ANYDATA_PRODUCT_ADU_E100A 0x6501
|
#define ANYDATA_PRODUCT_ADU_E100A 0x6501
|
||||||
@ -119,8 +120,6 @@ static int option_send_setup(struct usb_serial_port *port);
|
|||||||
#define BANDRICH_PRODUCT_C100_1 0x1002
|
#define BANDRICH_PRODUCT_C100_1 0x1002
|
||||||
#define BANDRICH_PRODUCT_C100_2 0x1003
|
#define BANDRICH_PRODUCT_C100_2 0x1003
|
||||||
|
|
||||||
#define DELL_VENDOR_ID 0x413C
|
|
||||||
|
|
||||||
static struct usb_device_id option_ids[] = {
|
static struct usb_device_id option_ids[] = {
|
||||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
|
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
|
||||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
|
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
|
||||||
@ -171,11 +170,16 @@ static struct usb_device_id option_ids[] = {
|
|||||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
|
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
|
||||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
|
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
|
||||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
|
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
|
||||||
|
{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
|
||||||
|
{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
|
||||||
|
{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) }, /* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
|
||||||
|
{ USB_DEVICE(DELL_VENDOR_ID, 0x8117) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */
|
||||||
|
{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
|
||||||
|
{ USB_DEVICE(DELL_VENDOR_ID, 0x8128) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */
|
||||||
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
|
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
|
||||||
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
|
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
|
||||||
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
|
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
|
||||||
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
|
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
|
||||||
{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard */
|
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||||
|
@ -818,19 +818,17 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
|
|||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case TCGETS:
|
case TCGETS:
|
||||||
if (copy_to_user(user_arg, port->tty->termios,
|
if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
|
||||||
sizeof(struct ktermios))) {
|
port->tty->termios))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case TCSETS:
|
case TCSETS:
|
||||||
case TCSETSW: /* FIXME: this is not the same! */
|
case TCSETSW: /* FIXME: this is not the same! */
|
||||||
case TCSETSF: /* FIXME: this is not the same! */
|
case TCSETSF: /* FIXME: this is not the same! */
|
||||||
if (copy_from_user(port->tty->termios, user_arg,
|
if (user_termios_to_kernel_termios(port->tty->termios,
|
||||||
sizeof(struct ktermios))) {
|
(struct ktermios __user *)arg))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
oti6858_set_termios(port, NULL);
|
oti6858_set_termios(port, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -74,13 +74,13 @@
|
|||||||
#include <linux/usb/serial.h>
|
#include <linux/usb/serial.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_USB_SAFE_PADDED
|
#ifndef CONFIG_USB_SERIAL_SAFE_PADDED
|
||||||
#define CONFIG_USB_SAFE_PADDED 0
|
#define CONFIG_USB_SERIAL_SAFE_PADDED 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int debug;
|
static int debug;
|
||||||
static int safe = 1;
|
static int safe = 1;
|
||||||
static int padded = CONFIG_USB_SAFE_PADDED;
|
static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
|
||||||
|
|
||||||
#define DRIVER_VERSION "v0.0b"
|
#define DRIVER_VERSION "v0.0b"
|
||||||
#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
|
#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
|
||||||
|
@ -104,6 +104,8 @@ static struct usb_device_id id_table [] = {
|
|||||||
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
|
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
|
||||||
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID),
|
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID),
|
||||||
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
|
.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 },
|
.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),
|
||||||
|
@ -48,6 +48,9 @@
|
|||||||
#define SONY_CLIE_UX50_ID 0x0144
|
#define SONY_CLIE_UX50_ID 0x0144
|
||||||
#define SONY_CLIE_TJ25_ID 0x0169
|
#define SONY_CLIE_TJ25_ID 0x0169
|
||||||
|
|
||||||
|
#define ACER_VENDOR_ID 0x0502
|
||||||
|
#define ACER_S10_ID 0x0001
|
||||||
|
|
||||||
#define SAMSUNG_VENDOR_ID 0x04E8
|
#define SAMSUNG_VENDOR_ID 0x04E8
|
||||||
#define SAMSUNG_SCH_I330_ID 0x8001
|
#define SAMSUNG_SCH_I330_ID 0x8001
|
||||||
#define SAMSUNG_SPH_I500_ID 0x6601
|
#define SAMSUNG_SPH_I500_ID 0x6601
|
||||||
|
@ -342,7 +342,7 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100,
|
|||||||
US_FL_FIX_CAPACITY),
|
US_FL_FIX_CAPACITY),
|
||||||
|
|
||||||
/* Reported by Emil Larsson <emil@swip.net> */
|
/* Reported by Emil Larsson <emil@swip.net> */
|
||||||
UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0100,
|
UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101,
|
||||||
"NIKON",
|
"NIKON",
|
||||||
"NIKON DSC D80",
|
"NIKON DSC D80",
|
||||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||||
|
@ -112,13 +112,6 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
|
|||||||
MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
|
MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
|
||||||
|
|
||||||
|
|
||||||
/* These are used to make sure the module doesn't unload before all the
|
|
||||||
* threads have exited.
|
|
||||||
*/
|
|
||||||
static atomic_t total_threads = ATOMIC_INIT(0);
|
|
||||||
static DECLARE_COMPLETION(threads_gone);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The entries in this table correspond, line for line,
|
* The entries in this table correspond, line for line,
|
||||||
* with the entries of us_unusual_dev_list[].
|
* with the entries of us_unusual_dev_list[].
|
||||||
@ -879,9 +872,6 @@ static void quiesce_and_remove_host(struct us_data *us)
|
|||||||
usb_stor_stop_transport(us);
|
usb_stor_stop_transport(us);
|
||||||
wake_up(&us->delay_wait);
|
wake_up(&us->delay_wait);
|
||||||
|
|
||||||
/* It doesn't matter if the SCSI-scanning thread is still running.
|
|
||||||
* The thread will exit when it sees the DISCONNECTING flag. */
|
|
||||||
|
|
||||||
/* queuecommand won't accept any new commands and the control
|
/* queuecommand won't accept any new commands and the control
|
||||||
* thread won't execute a previously-queued command. If there
|
* thread won't execute a previously-queued command. If there
|
||||||
* is such a command pending, complete it with an error. */
|
* is such a command pending, complete it with an error. */
|
||||||
@ -891,12 +881,16 @@ static void quiesce_and_remove_host(struct us_data *us)
|
|||||||
scsi_lock(host);
|
scsi_lock(host);
|
||||||
us->srb->scsi_done(us->srb);
|
us->srb->scsi_done(us->srb);
|
||||||
us->srb = NULL;
|
us->srb = NULL;
|
||||||
|
complete(&us->notify); /* in case of an abort */
|
||||||
scsi_unlock(host);
|
scsi_unlock(host);
|
||||||
}
|
}
|
||||||
mutex_unlock(&us->dev_mutex);
|
mutex_unlock(&us->dev_mutex);
|
||||||
|
|
||||||
/* Now we own no commands so it's safe to remove the SCSI host */
|
/* Now we own no commands so it's safe to remove the SCSI host */
|
||||||
scsi_remove_host(host);
|
scsi_remove_host(host);
|
||||||
|
|
||||||
|
/* Wait for the SCSI-scanning thread to stop */
|
||||||
|
wait_for_completion(&us->scanning_done);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second stage of disconnect processing: deallocate all resources */
|
/* Second stage of disconnect processing: deallocate all resources */
|
||||||
@ -947,9 +941,8 @@ retry:
|
|||||||
/* Should we unbind if no devices were detected? */
|
/* Should we unbind if no devices were detected? */
|
||||||
}
|
}
|
||||||
|
|
||||||
scsi_host_put(us_to_host(us));
|
|
||||||
usb_autopm_put_interface(us->pusb_intf);
|
usb_autopm_put_interface(us->pusb_intf);
|
||||||
complete_and_exit(&threads_gone, 0);
|
complete_and_exit(&us->scanning_done, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -984,6 +977,7 @@ static int storage_probe(struct usb_interface *intf,
|
|||||||
init_MUTEX_LOCKED(&(us->sema));
|
init_MUTEX_LOCKED(&(us->sema));
|
||||||
init_completion(&(us->notify));
|
init_completion(&(us->notify));
|
||||||
init_waitqueue_head(&us->delay_wait);
|
init_waitqueue_head(&us->delay_wait);
|
||||||
|
init_completion(&us->scanning_done);
|
||||||
|
|
||||||
/* Associate the us_data structure with the USB device */
|
/* Associate the us_data structure with the USB device */
|
||||||
result = associate_dev(us, intf);
|
result = associate_dev(us, intf);
|
||||||
@ -1033,11 +1027,6 @@ static int storage_probe(struct usb_interface *intf,
|
|||||||
goto BadDevice;
|
goto BadDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Take a reference to the host for the scanning thread and
|
|
||||||
* count it among all the threads we have launched. Then
|
|
||||||
* start it up. */
|
|
||||||
scsi_host_get(us_to_host(us));
|
|
||||||
atomic_inc(&total_threads);
|
|
||||||
usb_autopm_get_interface(intf); /* dropped in the scanning thread */
|
usb_autopm_get_interface(intf); /* dropped in the scanning thread */
|
||||||
wake_up_process(th);
|
wake_up_process(th);
|
||||||
|
|
||||||
@ -1104,16 +1093,6 @@ static void __exit usb_stor_exit(void)
|
|||||||
US_DEBUGP("-- calling usb_deregister()\n");
|
US_DEBUGP("-- calling usb_deregister()\n");
|
||||||
usb_deregister(&usb_storage_driver) ;
|
usb_deregister(&usb_storage_driver) ;
|
||||||
|
|
||||||
/* Don't return until all of our control and scanning threads
|
|
||||||
* have exited. Since each thread signals threads_gone as its
|
|
||||||
* last act, we have to call wait_for_completion the right number
|
|
||||||
* of times.
|
|
||||||
*/
|
|
||||||
while (atomic_read(&total_threads) > 0) {
|
|
||||||
wait_for_completion(&threads_gone);
|
|
||||||
atomic_dec(&total_threads);
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_usual_clear_present(USB_US_TYPE_STOR);
|
usb_usual_clear_present(USB_US_TYPE_STOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +150,7 @@ struct us_data {
|
|||||||
struct semaphore sema; /* to sleep thread on */
|
struct semaphore sema; /* to sleep thread on */
|
||||||
struct completion notify; /* thread begin/end */
|
struct completion notify; /* thread begin/end */
|
||||||
wait_queue_head_t delay_wait; /* wait during scan, reset */
|
wait_queue_head_t delay_wait; /* wait during scan, reset */
|
||||||
|
struct completion scanning_done; /* wait for scan thread */
|
||||||
|
|
||||||
/* subdriver information */
|
/* subdriver information */
|
||||||
void *extra; /* Any extra data */
|
void *extra; /* Any extra data */
|
||||||
|
Loading…
Reference in New Issue
Block a user