aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2007-05-01 00:24:54 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-05-01 00:24:54 -0400
commitbc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775 (patch)
tree427fcf2a7287c16d4b5aa6cbf494d59579a6a8b1 /drivers/usb/class
parent3d29cdff999c37b3876082278a8134a0642a02cd (diff)
parentdc87c3985e9b442c60994308a96f887579addc39 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/usb/input/Makefile drivers/usb/input/gtco.c
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-acm.c114
-rw-r--r--drivers/usb/class/cdc-acm.h3
-rw-r--r--drivers/usb/class/usblp.c6
3 files changed, 106 insertions, 17 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 98199628e394..14de3b1b6a20 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -212,7 +212,41 @@ static int acm_write_start(struct acm *acm)
212 } 212 }
213 return rc; 213 return rc;
214} 214}
215/*
216 * attributes exported through sysfs
217 */
218static ssize_t show_caps
219(struct device *dev, struct device_attribute *attr, char *buf)
220{
221 struct usb_interface *intf = to_usb_interface(dev);
222 struct acm *acm = usb_get_intfdata(intf);
223
224 return sprintf(buf, "%d", acm->ctrl_caps);
225}
226static DEVICE_ATTR(bmCapabilities, S_IRUGO, show_caps, NULL);
227
228static ssize_t show_country_codes
229(struct device *dev, struct device_attribute *attr, char *buf)
230{
231 struct usb_interface *intf = to_usb_interface(dev);
232 struct acm *acm = usb_get_intfdata(intf);
233
234 memcpy(buf, acm->country_codes, acm->country_code_size);
235 return acm->country_code_size;
236}
215 237
238static DEVICE_ATTR(wCountryCodes, S_IRUGO, show_country_codes, NULL);
239
240static ssize_t show_country_rel_date
241(struct device *dev, struct device_attribute *attr, char *buf)
242{
243 struct usb_interface *intf = to_usb_interface(dev);
244 struct acm *acm = usb_get_intfdata(intf);
245
246 return sprintf(buf, "%d", acm->country_rel_date);
247}
248
249static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL);
216/* 250/*
217 * Interrupt handlers for various ACM device responses 251 * Interrupt handlers for various ACM device responses
218 */ 252 */
@@ -326,10 +360,16 @@ static void acm_rx_tasklet(unsigned long _acm)
326 struct tty_struct *tty = acm->tty; 360 struct tty_struct *tty = acm->tty;
327 struct acm_ru *rcv; 361 struct acm_ru *rcv;
328 unsigned long flags; 362 unsigned long flags;
329 int i = 0; 363 unsigned char throttled;
330 dbg("Entering acm_rx_tasklet"); 364 dbg("Entering acm_rx_tasklet");
331 365
332 if (!ACM_READY(acm) || acm->throttle) 366 if (!ACM_READY(acm))
367 return;
368
369 spin_lock_irqsave(&acm->throttle_lock, flags);
370 throttled = acm->throttle;
371 spin_unlock_irqrestore(&acm->throttle_lock, flags);
372 if (throttled)
333 return; 373 return;
334 374
335next_buffer: 375next_buffer:
@@ -346,22 +386,20 @@ next_buffer:
346 dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); 386 dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
347 387
348 tty_buffer_request_room(tty, buf->size); 388 tty_buffer_request_room(tty, buf->size);
349 if (!acm->throttle) 389 spin_lock_irqsave(&acm->throttle_lock, flags);
390 throttled = acm->throttle;
391 spin_unlock_irqrestore(&acm->throttle_lock, flags);
392 if (!throttled)
350 tty_insert_flip_string(tty, buf->base, buf->size); 393 tty_insert_flip_string(tty, buf->base, buf->size);
351 tty_flip_buffer_push(tty); 394 tty_flip_buffer_push(tty);
352 395
353 spin_lock(&acm->throttle_lock); 396 if (throttled) {
354 if (acm->throttle) { 397 dbg("Throttling noticed");
355 dbg("Throtteling noticed");
356 memmove(buf->base, buf->base + i, buf->size - i);
357 buf->size -= i;
358 spin_unlock(&acm->throttle_lock);
359 spin_lock_irqsave(&acm->read_lock, flags); 398 spin_lock_irqsave(&acm->read_lock, flags);
360 list_add(&buf->list, &acm->filled_read_bufs); 399 list_add(&buf->list, &acm->filled_read_bufs);
361 spin_unlock_irqrestore(&acm->read_lock, flags); 400 spin_unlock_irqrestore(&acm->read_lock, flags);
362 return; 401 return;
363 } 402 }
364 spin_unlock(&acm->throttle_lock);
365 403
366 spin_lock_irqsave(&acm->read_lock, flags); 404 spin_lock_irqsave(&acm->read_lock, flags);
367 list_add(&buf->list, &acm->spare_read_bufs); 405 list_add(&buf->list, &acm->spare_read_bufs);
@@ -467,7 +505,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
467 goto bail_out; 505 goto bail_out;
468 } 506 }
469 507
470 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS)) 508 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
509 (acm->ctrl_caps & USB_CDC_CAP_LINE))
471 goto full_bailout; 510 goto full_bailout;
472 511
473 INIT_LIST_HEAD(&acm->spare_read_urbs); 512 INIT_LIST_HEAD(&acm->spare_read_urbs);
@@ -480,6 +519,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
480 list_add(&(acm->rb[i].list), &acm->spare_read_bufs); 519 list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
481 } 520 }
482 521
522 acm->throttle = 0;
523
483 tasklet_schedule(&acm->urb_task); 524 tasklet_schedule(&acm->urb_task);
484 525
485done: 526done:
@@ -507,6 +548,7 @@ static void acm_tty_unregister(struct acm *acm)
507 usb_free_urb(acm->writeurb); 548 usb_free_urb(acm->writeurb);
508 for (i = 0; i < nr; i++) 549 for (i = 0; i < nr; i++)
509 usb_free_urb(acm->ru[i].urb); 550 usb_free_urb(acm->ru[i].urb);
551 kfree(acm->country_codes);
510 kfree(acm); 552 kfree(acm);
511} 553}
512 554
@@ -754,6 +796,7 @@ static int acm_probe (struct usb_interface *intf,
754 const struct usb_device_id *id) 796 const struct usb_device_id *id)
755{ 797{
756 struct usb_cdc_union_desc *union_header = NULL; 798 struct usb_cdc_union_desc *union_header = NULL;
799 struct usb_cdc_country_functional_desc *cfd = NULL;
757 char *buffer = intf->altsetting->extra; 800 char *buffer = intf->altsetting->extra;
758 int buflen = intf->altsetting->extralen; 801 int buflen = intf->altsetting->extralen;
759 struct usb_interface *control_interface; 802 struct usb_interface *control_interface;
@@ -817,8 +860,9 @@ static int acm_probe (struct usb_interface *intf,
817 union_header = (struct usb_cdc_union_desc *) 860 union_header = (struct usb_cdc_union_desc *)
818 buffer; 861 buffer;
819 break; 862 break;
820 case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */ 863 case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
821 break; /* for now we ignore it */ 864 cfd = (struct usb_cdc_country_functional_desc *)buffer;
865 break;
822 case USB_CDC_HEADER_TYPE: /* maybe check version */ 866 case USB_CDC_HEADER_TYPE: /* maybe check version */
823 break; /* for now we ignore it */ 867 break; /* for now we ignore it */
824 case USB_CDC_ACM_TYPE: 868 case USB_CDC_ACM_TYPE:
@@ -976,6 +1020,34 @@ skip_normal_probe:
976 goto alloc_fail7; 1020 goto alloc_fail7;
977 } 1021 }
978 1022
1023 usb_set_intfdata (intf, acm);
1024
1025 i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
1026 if (i < 0)
1027 goto alloc_fail8;
1028
1029 if (cfd) { /* export the country data */
1030 acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL);
1031 if (!acm->country_codes)
1032 goto skip_countries;
1033 acm->country_code_size = cfd->bLength - 4;
1034 memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, cfd->bLength - 4);
1035 acm->country_rel_date = cfd->iCountryCodeRelDate;
1036
1037 i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
1038 if (i < 0) {
1039 kfree(acm->country_codes);
1040 goto skip_countries;
1041 }
1042
1043 i = device_create_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
1044 if (i < 0) {
1045 kfree(acm->country_codes);
1046 goto skip_countries;
1047 }
1048 }
1049
1050skip_countries:
979 usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), 1051 usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
980 acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); 1052 acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
981 acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1053 acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -999,9 +1071,10 @@ skip_normal_probe:
999 tty_register_device(acm_tty_driver, minor, &control_interface->dev); 1071 tty_register_device(acm_tty_driver, minor, &control_interface->dev);
1000 1072
1001 acm_table[minor] = acm; 1073 acm_table[minor] = acm;
1002 usb_set_intfdata (intf, acm);
1003 return 0;
1004 1074
1075 return 0;
1076alloc_fail8:
1077 usb_free_urb(acm->writeurb);
1005alloc_fail7: 1078alloc_fail7:
1006 for (i = 0; i < num_rx_buf; i++) 1079 for (i = 0; i < num_rx_buf; i++)
1007 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); 1080 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
@@ -1020,7 +1093,7 @@ alloc_fail:
1020 1093
1021static void acm_disconnect(struct usb_interface *intf) 1094static void acm_disconnect(struct usb_interface *intf)
1022{ 1095{
1023 struct acm *acm = usb_get_intfdata (intf); 1096 struct acm *acm = usb_get_intfdata(intf);
1024 struct usb_device *usb_dev = interface_to_usbdev(intf); 1097 struct usb_device *usb_dev = interface_to_usbdev(intf);
1025 int i; 1098 int i;
1026 1099
@@ -1034,6 +1107,11 @@ static void acm_disconnect(struct usb_interface *intf)
1034 mutex_unlock(&open_mutex); 1107 mutex_unlock(&open_mutex);
1035 return; 1108 return;
1036 } 1109 }
1110 if (acm->country_codes){
1111 device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
1112 device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
1113 }
1114 device_remove_file(&intf->dev, &dev_attr_bmCapabilities);
1037 acm->dev = NULL; 1115 acm->dev = NULL;
1038 usb_set_intfdata(acm->control, NULL); 1116 usb_set_intfdata(acm->control, NULL);
1039 usb_set_intfdata(acm->data, NULL); 1117 usb_set_intfdata(acm->data, NULL);
@@ -1092,6 +1170,10 @@ static struct usb_device_id acm_ids[] = {
1092 { USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */ 1170 { USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
1093 .driver_info = SINGLE_RX_URB, /* firmware bug */ 1171 .driver_info = SINGLE_RX_URB, /* firmware bug */
1094 }, 1172 },
1173 { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
1174 .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
1175 },
1176
1095 /* control interfaces with various AT-command sets */ 1177 /* control interfaces with various AT-command sets */
1096 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, 1178 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
1097 USB_CDC_ACM_PROTO_AT_V25TER) }, 1179 USB_CDC_ACM_PROTO_AT_V25TER) },
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 1bcaea32cfc1..09f7765dbf8d 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -91,6 +91,9 @@ struct acm {
91 struct urb *ctrlurb, *writeurb; /* urbs */ 91 struct urb *ctrlurb, *writeurb; /* urbs */
92 u8 *ctrl_buffer; /* buffers of urbs */ 92 u8 *ctrl_buffer; /* buffers of urbs */
93 dma_addr_t ctrl_dma; /* dma handles of buffers */ 93 dma_addr_t ctrl_dma; /* dma handles of buffers */
94 u8 *country_codes; /* country codes from device */
95 unsigned int country_code_size; /* size of this buffer */
96 unsigned int country_rel_date; /* release date of version */
94 struct acm_wb wb[ACM_NW]; 97 struct acm_wb wb[ACM_NW];
95 struct acm_ru ru[ACM_NR]; 98 struct acm_ru ru[ACM_NR];
96 struct acm_rb rb[ACM_NR]; 99 struct acm_rb rb[ACM_NR];
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 63e50a1f1396..6584cf00f7f3 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -202,6 +202,7 @@ struct quirk_printer_struct {
202 202
203#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */ 203#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
204#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */ 204#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
205#define USBLP_QUIRK_BAD_CLASS 0x4 /* descriptor uses vendor-specific Class or SubClass */
205 206
206static const struct quirk_printer_struct quirk_printers[] = { 207static const struct quirk_printer_struct quirk_printers[] = {
207 { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */ 208 { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
@@ -218,6 +219,7 @@ static const struct quirk_printer_struct quirk_printers[] = {
218 { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ 219 { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
219 { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ 220 { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
220 { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */ 221 { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */
222 { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */
221 { 0, 0 } 223 { 0, 0 }
222}; 224};
223 225
@@ -1048,7 +1050,8 @@ static int usblp_select_alts(struct usblp *usblp)
1048 ifd = &if_alt->altsetting[i]; 1050 ifd = &if_alt->altsetting[i];
1049 1051
1050 if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1) 1052 if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1)
1051 continue; 1053 if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS))
1054 continue;
1052 1055
1053 if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL || 1056 if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
1054 ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL) 1057 ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL)
@@ -1232,6 +1235,7 @@ static struct usb_device_id usblp_ids [] = {
1232 { USB_INTERFACE_INFO(7, 1, 1) }, 1235 { USB_INTERFACE_INFO(7, 1, 1) },
1233 { USB_INTERFACE_INFO(7, 1, 2) }, 1236 { USB_INTERFACE_INFO(7, 1, 2) },
1234 { USB_INTERFACE_INFO(7, 1, 3) }, 1237 { USB_INTERFACE_INFO(7, 1, 3) },
1238 { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */
1235 { } /* Terminating entry */ 1239 { } /* Terminating entry */
1236}; 1240};
1237 1241