acm.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:19k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * acm.c  Version 0.21
  3.  *
  4.  * Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de>
  5.  * Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
  6.  * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com>
  7.  * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
  8.  *
  9.  * USB Abstract Control Model driver for USB modems and ISDN adapters
  10.  *
  11.  * Sponsored by SuSE
  12.  *
  13.  * ChangeLog:
  14.  * v0.9  - thorough cleaning, URBification, almost a rewrite
  15.  * v0.10 - some more cleanups
  16.  * v0.11 - fixed flow control, read error doesn't stop reads
  17.  * v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
  18.  * v0.13 - added termios, added hangup
  19.  * v0.14 - sized down struct acm
  20.  * v0.15 - fixed flow control again - characters could be lost
  21.  * v0.16 - added code for modems with swapped data and control interfaces
  22.  * v0.17 - added new style probing
  23.  * v0.18 - fixed new style probing for devices with more configurations
  24.  * v0.19 - fixed CLOCAL handling (thanks to Richard Shih-Ping Chan)
  25.  * v0.20 - switched to probing on interface (rather than device) class
  26.  * v0.21 - revert to probing on device for devices with multiple configs
  27.  */
  28. /*
  29.  * This program is free software; you can redistribute it and/or modify
  30.  * it under the terms of the GNU General Public License as published by
  31.  * the Free Software Foundation; either version 2 of the License, or
  32.  * (at your option) any later version.
  33.  *
  34.  * This program is distributed in the hope that it will be useful,
  35.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  36.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  37.  * GNU General Public License for more details.
  38.  *
  39.  * You should have received a copy of the GNU General Public License
  40.  * along with this program; if not, write to the Free Software
  41.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  42.  */
  43. #include <linux/kernel.h>
  44. #include <linux/sched.h>
  45. #include <linux/signal.h>
  46. #include <linux/errno.h>
  47. #include <linux/poll.h>
  48. #include <linux/init.h>
  49. #include <linux/slab.h>
  50. #include <linux/fcntl.h>
  51. #include <linux/tty.h>
  52. #include <linux/tty_driver.h>
  53. #include <linux/tty_flip.h>
  54. #include <linux/module.h>
  55. #include <linux/smp_lock.h>
  56. #undef DEBUG
  57. #include <linux/usb.h>
  58. /*
  59.  * Version Information
  60.  */
  61. #define DRIVER_VERSION "v0.21"
  62. #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
  63. #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
  64. /*
  65.  * CMSPAR, some architectures can't have space and mark parity.
  66.  */
  67. #ifndef CMSPAR
  68. #define CMSPAR 0
  69. #endif
  70. /*
  71.  * Major and minor numbers.
  72.  */
  73. #define ACM_TTY_MAJOR 166
  74. #define ACM_TTY_MINORS 32
  75. /*
  76.  * Requests.
  77.  */
  78. #define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
  79. #define ACM_REQ_COMMAND 0x00
  80. #define ACM_REQ_RESPONSE 0x01
  81. #define ACM_REQ_SET_FEATURE 0x02
  82. #define ACM_REQ_GET_FEATURE 0x03
  83. #define ACM_REQ_CLEAR_FEATURE 0x04
  84. #define ACM_REQ_SET_LINE 0x20
  85. #define ACM_REQ_GET_LINE 0x21
  86. #define ACM_REQ_SET_CONTROL 0x22
  87. #define ACM_REQ_SEND_BREAK 0x23
  88. /*
  89.  * IRQs.
  90.  */
  91. #define ACM_IRQ_NETWORK 0x00
  92. #define ACM_IRQ_LINE_STATE 0x20
  93. /*
  94.  * Output control lines.
  95.  */
  96. #define ACM_CTRL_DTR 0x01
  97. #define ACM_CTRL_RTS 0x02
  98. /*
  99.  * Input control lines and line errors.
  100.  */
  101. #define ACM_CTRL_DCD 0x01
  102. #define ACM_CTRL_DSR 0x02
  103. #define ACM_CTRL_BRK 0x04
  104. #define ACM_CTRL_RI 0x08
  105. #define ACM_CTRL_FRAMING 0x10
  106. #define ACM_CTRL_PARITY 0x20
  107. #define ACM_CTRL_OVERRUN 0x40
  108. /*
  109.  * Line speed and caracter encoding.
  110.  */
  111. struct acm_line {
  112. __u32 speed;
  113. __u8 stopbits;
  114. __u8 parity;
  115. __u8 databits;
  116. } __attribute__ ((packed));
  117. /*
  118.  * Internal driver structures.
  119.  */
  120. struct acm {
  121. struct usb_device *dev; /* the coresponding usb device */
  122. struct usb_interface *iface; /* the interfaces - +0 control +1 data */
  123. struct tty_struct *tty; /* the coresponding tty */
  124. struct urb ctrlurb, readurb, writeurb; /* urbs */
  125. struct acm_line line; /* line coding (bits, stop, parity) */
  126. struct tq_struct tqueue; /* task queue for line discipline waking up */
  127. unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
  128. unsigned int ctrlout; /* output control lines (DTR, RTS) */
  129. unsigned int writesize; /* max packet size for the output bulk endpoint */
  130. unsigned int used; /* someone has this acm's device open */
  131. unsigned int minor; /* acm minor number */
  132. unsigned char throttle; /* throttled by tty layer */
  133. unsigned char clocal; /* termios CLOCAL */
  134. };
  135. static struct usb_driver acm_driver;
  136. static struct tty_driver acm_tty_driver;
  137. static struct acm *acm_table[ACM_TTY_MINORS];
  138. #define ACM_READY(acm) (acm && acm->dev && acm->used)
  139. /*
  140.  * Functions for ACM control messages.
  141.  */
  142. static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
  143. {
  144. int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
  145. request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
  146. dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
  147. return retval < 0 ? retval : 0;
  148. }
  149. #define acm_set_control(acm, control) acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
  150. #define acm_set_line(acm, line) acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
  151. #define acm_send_break(acm, ms) acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
  152. /*
  153.  * Interrupt handler for various ACM control events
  154.  */
  155. static void acm_ctrl_irq(struct urb *urb)
  156. {
  157. struct acm *acm = urb->context;
  158. devrequest *dr = urb->transfer_buffer;
  159. unsigned char *data = (unsigned char *)(dr + 1);
  160. int newctrl;
  161. if (!ACM_READY(acm)) return;
  162. if (urb->status < 0) {
  163. dbg("nonzero ctrl irq status received: %d", urb->status);
  164. return;
  165. }
  166. switch (dr->request) {
  167. case ACM_IRQ_NETWORK:
  168. dbg("%s network", data[0] ? "connected to" : "disconnected from");
  169. return;
  170. case ACM_IRQ_LINE_STATE:
  171. newctrl = le16_to_cpup((__u16 *) data);
  172. if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
  173. dbg("calling hangup");
  174. tty_hangup(acm->tty);
  175. }
  176. acm->ctrlin = newctrl;
  177. dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
  178. acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
  179. acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI  ? '+' : '-',
  180. acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
  181. acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
  182. return;
  183. default:
  184. dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
  185. dr->request, dr->index, dr->length, data[0], data[1]);
  186. return;
  187. }
  188. }
  189. static void acm_read_bulk(struct urb *urb)
  190. {
  191. struct acm *acm = urb->context;
  192. struct tty_struct *tty = acm->tty;
  193. unsigned char *data = urb->transfer_buffer;
  194. int i = 0;
  195. if (!ACM_READY(acm)) return;
  196. if (urb->status)
  197. dbg("nonzero read bulk status received: %d", urb->status);
  198. if (!urb->status & !acm->throttle)  {
  199. for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
  200. /* if we insert more than TTY_FLIPBUF_SIZE characters,
  201.  * we drop them. */
  202. if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
  203. tty_flip_buffer_push(tty);
  204. }
  205. tty_insert_flip_char(tty, data[i], 0);
  206. }
  207. tty_flip_buffer_push(tty);
  208. }
  209. if (acm->throttle) {
  210. memmove(data, data + i, urb->actual_length - i);
  211. urb->actual_length -= i;
  212. return;
  213. }
  214. urb->actual_length = 0;
  215. urb->dev = acm->dev;
  216. if (usb_submit_urb(urb))
  217. dbg("failed resubmitting read urb");
  218. }
  219. static void acm_write_bulk(struct urb *urb)
  220. {
  221. struct acm *acm = (struct acm *)urb->context;
  222. if (!ACM_READY(acm)) return;
  223. if (urb->status)
  224. dbg("nonzero write bulk status received: %d", urb->status);
  225. queue_task(&acm->tqueue, &tq_immediate);
  226. mark_bh(IMMEDIATE_BH);
  227. }
  228. static void acm_softint(void *private)
  229. {
  230. struct acm *acm = private;
  231. struct tty_struct *tty = acm->tty;
  232. if (!ACM_READY(acm)) return;
  233. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
  234. (tty->ldisc.write_wakeup)(tty);
  235. wake_up_interruptible(&tty->write_wait);
  236. }
  237. /*
  238.  * TTY handlers
  239.  */
  240. static int acm_tty_open(struct tty_struct *tty, struct file *filp)
  241. {
  242. struct acm *acm = acm_table[MINOR(tty->device)];
  243. if (!acm || !acm->dev) return -EINVAL;
  244. tty->driver_data = acm;
  245. acm->tty = tty;
  246. MOD_INC_USE_COUNT;
  247.         lock_kernel();
  248. if (acm->used++) {
  249.                 unlock_kernel();
  250.                 return 0;
  251.         }
  252.         unlock_kernel();
  253. acm->ctrlurb.dev = acm->dev;
  254. if (usb_submit_urb(&acm->ctrlurb))
  255. dbg("usb_submit_urb(ctrl irq) failed");
  256. acm->readurb.dev = acm->dev;
  257. if (usb_submit_urb(&acm->readurb))
  258. dbg("usb_submit_urb(read bulk) failed");
  259. acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
  260. /* force low_latency on so that our tty_push actually forces the data through, 
  261.    otherwise it is scheduled, and with high data rates data can get lost. */
  262. tty->low_latency = 1;
  263. return 0;
  264. }
  265. static void acm_tty_close(struct tty_struct *tty, struct file *filp)
  266. {
  267. struct acm *acm = tty->driver_data;
  268. if (!acm || !acm->used) return;
  269. if (!--acm->used) {
  270. if (acm->dev) {
  271. acm_set_control(acm, acm->ctrlout = 0);
  272. usb_unlink_urb(&acm->ctrlurb);
  273. usb_unlink_urb(&acm->writeurb);
  274. usb_unlink_urb(&acm->readurb);
  275. } else {
  276. tty_unregister_devfs(&acm_tty_driver, acm->minor);
  277. acm_table[acm->minor] = NULL;
  278. kfree(acm);
  279. }
  280. }
  281. MOD_DEC_USE_COUNT;
  282. }
  283. static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
  284. {
  285. struct acm *acm = tty->driver_data;
  286. if (!ACM_READY(acm)) return -EINVAL;
  287. if (acm->writeurb.status == -EINPROGRESS) return 0;
  288. if (!count) return 0;
  289. count = (count > acm->writesize) ? acm->writesize : count;
  290. if (from_user)
  291. copy_from_user(acm->writeurb.transfer_buffer, buf, count);
  292. else
  293. memcpy(acm->writeurb.transfer_buffer, buf, count);
  294. acm->writeurb.transfer_buffer_length = count;
  295. acm->writeurb.dev = acm->dev;
  296. if (usb_submit_urb(&acm->writeurb))
  297. dbg("usb_submit_urb(write bulk) failed");
  298. return count;
  299. }
  300. static int acm_tty_write_room(struct tty_struct *tty)
  301. {
  302. struct acm *acm = tty->driver_data;
  303. if (!ACM_READY(acm)) return -EINVAL;
  304. return acm->writeurb.status == -EINPROGRESS ? 0 : acm->writesize;
  305. }
  306. static int acm_tty_chars_in_buffer(struct tty_struct *tty)
  307. {
  308. struct acm *acm = tty->driver_data;
  309. if (!ACM_READY(acm)) return -EINVAL;
  310. return acm->writeurb.status == -EINPROGRESS ? acm->writeurb.transfer_buffer_length : 0;
  311. }
  312. static void acm_tty_throttle(struct tty_struct *tty)
  313. {
  314. struct acm *acm = tty->driver_data;
  315. if (!ACM_READY(acm)) return;
  316. acm->throttle = 1;
  317. }
  318. static void acm_tty_unthrottle(struct tty_struct *tty)
  319. {
  320. struct acm *acm = tty->driver_data;
  321. if (!ACM_READY(acm)) return;
  322. acm->throttle = 0;
  323. if (acm->readurb.status != -EINPROGRESS)
  324. acm_read_bulk(&acm->readurb);
  325. }
  326. static void acm_tty_break_ctl(struct tty_struct *tty, int state)
  327. {
  328. struct acm *acm = tty->driver_data;
  329. if (!ACM_READY(acm)) return;
  330. if (acm_send_break(acm, state ? 0xffff : 0))
  331. dbg("send break failed");
  332. }
  333. static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
  334. {
  335. struct acm *acm = tty->driver_data;
  336. unsigned int mask, newctrl;
  337. if (!ACM_READY(acm)) return -EINVAL;
  338. switch (cmd) {
  339. case TIOCMGET:
  340. return put_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
  341. (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
  342. (acm->ctrlin  & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
  343. (acm->ctrlin  & ACM_CTRL_RI  ? TIOCM_RI  : 0) |
  344. (acm->ctrlin  & ACM_CTRL_DCD ? TIOCM_CD  : 0) |
  345.  TIOCM_CTS, (unsigned long *) arg);
  346. case TIOCMSET:
  347. case TIOCMBIS:
  348. case TIOCMBIC:
  349. if (get_user(mask, (unsigned long *) arg))
  350. return -EFAULT;
  351. newctrl = acm->ctrlout;
  352. mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
  353. switch (cmd) {
  354. case TIOCMSET: newctrl  =  mask; break;
  355. case TIOCMBIS: newctrl |=  mask; break;
  356. case TIOCMBIC: newctrl &= ~mask; break;
  357. }
  358. if (acm->ctrlout == newctrl) return 0;
  359. return acm_set_control(acm, acm->ctrlout = newctrl);
  360. }
  361. return -ENOIOCTLCMD;
  362. }
  363. static __u32 acm_tty_speed[] = {
  364. 0, 50, 75, 110, 134, 150, 200, 300, 600,
  365. 1200, 1800, 2400, 4800, 9600, 19200, 38400,
  366. 57600, 115200, 230400, 460800, 500000, 576000,
  367. 921600, 1000000, 1152000, 1500000, 2000000,
  368. 2500000, 3000000, 3500000, 4000000
  369. };
  370. static __u8 acm_tty_size[] = {
  371. 5, 6, 7, 8
  372. };
  373. static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
  374. {
  375. struct acm *acm = tty->driver_data;
  376. struct termios *termios = tty->termios;
  377. struct acm_line newline;
  378. int newctrl = acm->ctrlout;
  379. if (!ACM_READY(acm)) return;
  380. newline.speed = cpu_to_le32p(acm_tty_speed +
  381. (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
  382. newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
  383. newline.parity = termios->c_cflag & PARENB ?
  384. (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
  385. newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
  386. acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
  387. if (!newline.speed) {
  388. newline.speed = acm->line.speed;
  389. newctrl &= ~ACM_CTRL_DTR;
  390. } else  newctrl |=  ACM_CTRL_DTR;
  391. if (newctrl != acm->ctrlout)
  392. acm_set_control(acm, acm->ctrlout = newctrl);
  393. if (memcmp(&acm->line, &newline, sizeof(struct acm_line))) {
  394. memcpy(&acm->line, &newline, sizeof(struct acm_line));
  395. dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
  396. acm_set_line(acm, &acm->line);
  397. }
  398. }
  399. /*
  400.  * USB probe and disconnect routines.
  401.  */
  402. static void *acm_probe(struct usb_device *dev, unsigned int ifnum,
  403.        const struct usb_device_id *id)
  404. {
  405. struct acm *acm;
  406. struct usb_config_descriptor *cfacm;
  407. struct usb_interface_descriptor *ifcom, *ifdata;
  408. struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
  409. int readsize, ctrlsize, minor, i;
  410. unsigned char *buf;
  411. for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
  412. cfacm = dev->config + i;
  413. dbg("probing config %d", cfacm->bConfigurationValue);
  414. if (cfacm->bNumInterfaces != 2 ||
  415.     usb_interface_claimed(cfacm->interface + 0) ||
  416.     usb_interface_claimed(cfacm->interface + 1))
  417. continue;
  418. ifcom = cfacm->interface[0].altsetting + 0;
  419. ifdata = cfacm->interface[1].altsetting + 0;
  420. if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) {
  421. ifcom = cfacm->interface[1].altsetting + 0;
  422. ifdata = cfacm->interface[0].altsetting + 0;
  423. if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2)
  424. continue;
  425. }
  426. if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
  427.     ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints < 1)
  428. continue;
  429. epctrl = ifcom->endpoint + 0;
  430. epread = ifdata->endpoint + 0;
  431. epwrite = ifdata->endpoint + 1;
  432. if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
  433.    (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
  434.    ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
  435. continue;
  436. if ((epread->bEndpointAddress & 0x80) != 0x80) {
  437. epread = ifdata->endpoint + 1;
  438. epwrite = ifdata->endpoint + 0;
  439. }
  440. usb_set_configuration(dev, cfacm->bConfigurationValue);
  441. for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
  442. if (acm_table[minor]) {
  443. err("no more free acm devices");
  444. return NULL;
  445. }
  446. if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
  447. err("out of memory");
  448. return NULL;
  449. }
  450. memset(acm, 0, sizeof(struct acm));
  451. ctrlsize = epctrl->wMaxPacketSize;
  452. readsize = epread->wMaxPacketSize;
  453. acm->writesize = epwrite->wMaxPacketSize;
  454. acm->iface = cfacm->interface;
  455. acm->minor = minor;
  456. acm->dev = dev;
  457. acm->tqueue.routine = acm_softint;
  458. acm->tqueue.data = acm;
  459. if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
  460. err("out of memory");
  461. kfree(acm);
  462. return NULL;
  463. }
  464. FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
  465. buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
  466. FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
  467. buf += ctrlsize, readsize, acm_read_bulk, acm);
  468. acm->readurb.transfer_flags |= USB_NO_FSBR;
  469. FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
  470. buf += readsize, acm->writesize, acm_write_bulk, acm);
  471. acm->writeurb.transfer_flags |= USB_NO_FSBR;
  472. printk(KERN_INFO "ttyACM%d: USB ACM devicen", minor);
  473. acm_set_control(acm, acm->ctrlout);
  474. acm->line.speed = cpu_to_le32(9600);
  475. acm->line.databits = 8;
  476. acm_set_line(acm, &acm->line);
  477. usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
  478. usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
  479. tty_register_devfs(&acm_tty_driver, 0, minor);
  480. return acm_table[minor] = acm;
  481. }
  482. return NULL;
  483. }
  484. static void acm_disconnect(struct usb_device *dev, void *ptr)
  485. {
  486. struct acm *acm = ptr;
  487. if (!acm || !acm->dev) {
  488. dbg("disconnect on nonexisting interface");
  489. return;
  490. }
  491. acm->dev = NULL;
  492. usb_unlink_urb(&acm->ctrlurb);
  493. usb_unlink_urb(&acm->readurb);
  494. usb_unlink_urb(&acm->writeurb);
  495. kfree(acm->ctrlurb.transfer_buffer);
  496. usb_driver_release_interface(&acm_driver, acm->iface + 0);
  497. usb_driver_release_interface(&acm_driver, acm->iface + 1);
  498. if (!acm->used) {
  499. tty_unregister_devfs(&acm_tty_driver, acm->minor);
  500. acm_table[acm->minor] = NULL;
  501. kfree(acm);
  502. return;
  503. }
  504. if (acm->tty)
  505. tty_hangup(acm->tty);
  506. }
  507. /*
  508.  * USB driver structure.
  509.  */
  510. static struct usb_device_id acm_ids[] = {
  511. { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
  512. { }
  513. };
  514. MODULE_DEVICE_TABLE (usb, acm_ids);
  515. static struct usb_driver acm_driver = {
  516. name: "acm",
  517. probe: acm_probe,
  518. disconnect: acm_disconnect,
  519. id_table: acm_ids,
  520. };
  521. /*
  522.  * TTY driver structures.
  523.  */
  524. static int acm_tty_refcount;
  525. static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
  526. static struct termios *acm_tty_termios[ACM_TTY_MINORS];
  527. static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
  528. static struct tty_driver acm_tty_driver = {
  529. magic: TTY_DRIVER_MAGIC,
  530. driver_name: "acm",
  531. name: "usb/acm/%d",
  532. major: ACM_TTY_MAJOR,
  533. minor_start: 0,
  534. num: ACM_TTY_MINORS,
  535. type: TTY_DRIVER_TYPE_SERIAL,
  536. subtype: SERIAL_TYPE_NORMAL,
  537. flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
  538. refcount: &acm_tty_refcount,
  539. table: acm_tty_table,
  540. termios: acm_tty_termios,
  541. termios_locked: acm_tty_termios_locked,
  542. open: acm_tty_open,
  543. close: acm_tty_close,
  544. write: acm_tty_write,
  545. write_room: acm_tty_write_room,
  546. ioctl: acm_tty_ioctl,
  547. throttle: acm_tty_throttle,
  548. unthrottle: acm_tty_unthrottle,
  549. chars_in_buffer: acm_tty_chars_in_buffer,
  550. break_ctl: acm_tty_break_ctl,
  551. set_termios: acm_tty_set_termios
  552. };
  553. /*
  554.  * Init / exit.
  555.  */
  556. static int __init acm_init(void)
  557. {
  558. acm_tty_driver.init_termios = tty_std_termios;
  559. acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  560. if (tty_register_driver(&acm_tty_driver))
  561. return -1;
  562. if (usb_register(&acm_driver) < 0) {
  563. tty_unregister_driver(&acm_tty_driver);
  564. return -1;
  565. }
  566. info(DRIVER_VERSION ":" DRIVER_DESC);
  567. return 0;
  568. }
  569. static void __exit acm_exit(void)
  570. {
  571. usb_deregister(&acm_driver);
  572. tty_unregister_driver(&acm_tty_driver);
  573. }
  574. module_init(acm_init);
  575. module_exit(acm_exit);
  576. MODULE_AUTHOR( DRIVER_AUTHOR );
  577. MODULE_DESCRIPTION( DRIVER_DESC );
  578. MODULE_LICENSE("GPL");