Advertisement
Perka

f_diag.c

Aug 6th, 2013
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.98 KB | None | 0 0
  1. /* drivers/usb/gadget/f_diag.c
  2. * Diag Function Device - Route ARM9 and ARM11 DIAG messages
  3. * between HOST and DEVICE.
  4. * Copyright (C) 2007 Google, Inc.
  5. * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  6. * Author: Brian Swetland <swetland@google.com>
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #include <linux/init.h>
  18. #include <linux/module.h>
  19. #include <linux/kernel.h>
  20. #include <linux/platform_device.h>
  21.  
  22. #include <mach/usbdiag.h>
  23.  
  24. #include <linux/usb/composite.h>
  25. #include <linux/usb/gadget.h>
  26. #include <linux/workqueue.h>
  27. #include <linux/debugfs.h>
  28.  
  29. static DEFINE_SPINLOCK(ch_lock);
  30. static LIST_HEAD(usb_diag_ch_list);
  31.  
  32. static struct usb_interface_descriptor intf_desc = {
  33. .bLength = sizeof intf_desc,
  34. .bDescriptorType = USB_DT_INTERFACE,
  35. .bNumEndpoints = 2,
  36. .bInterfaceClass = 0xFF,
  37. #if defined(CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE) || defined(CONFIG_SLP)
  38. .bInterfaceSubClass = 0x10,
  39. .bInterfaceProtocol = 0x01,
  40. #else
  41. .bInterfaceSubClass = 0xFF,
  42. .bInterfaceProtocol = 0xFF,
  43. #endif
  44. };
  45.  
  46. static struct usb_endpoint_descriptor hs_bulk_in_desc = {
  47. .bLength = USB_DT_ENDPOINT_SIZE,
  48. .bDescriptorType = USB_DT_ENDPOINT,
  49. .bEndpointAddress = USB_DIR_IN,
  50. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  51. .wMaxPacketSize = __constant_cpu_to_le16(512),
  52. .bInterval = 0,
  53. };
  54. static struct usb_endpoint_descriptor fs_bulk_in_desc = {
  55. .bLength = USB_DT_ENDPOINT_SIZE,
  56. .bDescriptorType = USB_DT_ENDPOINT,
  57. .bEndpointAddress = USB_DIR_IN,
  58. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  59. .wMaxPacketSize = __constant_cpu_to_le16(64),
  60. .bInterval = 0,
  61. };
  62.  
  63. static struct usb_endpoint_descriptor hs_bulk_out_desc = {
  64. .bLength = USB_DT_ENDPOINT_SIZE,
  65. .bDescriptorType = USB_DT_ENDPOINT,
  66. .bEndpointAddress = USB_DIR_OUT,
  67. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  68. .wMaxPacketSize = __constant_cpu_to_le16(512),
  69. .bInterval = 0,
  70. };
  71.  
  72. static struct usb_endpoint_descriptor fs_bulk_out_desc = {
  73. .bLength = USB_DT_ENDPOINT_SIZE,
  74. .bDescriptorType = USB_DT_ENDPOINT,
  75. .bEndpointAddress = USB_DIR_OUT,
  76. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  77. .wMaxPacketSize = __constant_cpu_to_le16(64),
  78. .bInterval = 0,
  79. };
  80.  
  81. static struct usb_descriptor_header *fs_diag_desc[] = {
  82. (struct usb_descriptor_header *) &intf_desc,
  83. (struct usb_descriptor_header *) &fs_bulk_in_desc,
  84. (struct usb_descriptor_header *) &fs_bulk_out_desc,
  85. NULL,
  86. };
  87. static struct usb_descriptor_header *hs_diag_desc[] = {
  88. (struct usb_descriptor_header *) &intf_desc,
  89. (struct usb_descriptor_header *) &hs_bulk_in_desc,
  90. (struct usb_descriptor_header *) &hs_bulk_out_desc,
  91. NULL,
  92. };
  93.  
  94. /**
  95. * struct diag_context - USB diag function driver private structure
  96. * @function: function structure for USB interface
  97. * @out: USB OUT endpoint struct
  98. * @in: USB IN endpoint struct
  99. * @in_desc: USB IN endpoint descriptor struct
  100. * @out_desc: USB OUT endpoint descriptor struct
  101. * @read_pool: List of requests used for Rx (OUT ep)
  102. * @write_pool: List of requests used for Tx (IN ep)
  103. * @config_work: Work item schedule after interface is configured to notify
  104. * CONNECT event to diag char driver and updating product id
  105. * and serial number to MODEM/IMEM.
  106. * @lock: Spinlock to proctect read_pool, write_pool lists
  107. * @cdev: USB composite device struct
  108. * @ch: USB diag channel
  109. *
  110. */
  111. struct diag_context {
  112. struct usb_function function;
  113. struct usb_ep *out;
  114. struct usb_ep *in;
  115. struct usb_endpoint_descriptor *in_desc;
  116. struct usb_endpoint_descriptor *out_desc;
  117. struct list_head read_pool;
  118. struct list_head write_pool;
  119. struct work_struct config_work;
  120. spinlock_t lock;
  121. unsigned configured;
  122. struct usb_composite_dev *cdev;
  123. int (*update_pid_and_serial_num)(uint32_t, const char *);
  124. struct usb_diag_ch ch;
  125.  
  126. /* pkt counters */
  127. unsigned long dpkts_tolaptop;
  128. unsigned long dpkts_tomodem;
  129. unsigned dpkts_tolaptop_pending;
  130. // zero_pky.patch by jagadish
  131. bool qxdm_ops;
  132. };
  133.  
  134. static inline struct diag_context *func_to_diag(struct usb_function *f)
  135. {
  136. return container_of(f, struct diag_context, function);
  137. }
  138.  
  139. static void usb_config_work_func(struct work_struct *work)
  140. {
  141. struct diag_context *ctxt = container_of(work,
  142. struct diag_context, config_work);
  143. struct usb_composite_dev *cdev = ctxt->cdev;
  144. struct usb_gadget_strings *table;
  145. struct usb_string *s;
  146.  
  147. if (ctxt->ch.notify)
  148. {
  149. ctxt->ch.notify(ctxt->ch.priv, USB_DIAG_CONNECT, NULL);
  150. // zero_pky.patch by jagadish
  151. ctxt->qxdm_ops = 0;
  152. }
  153. }
  154.  
  155. static void diag_write_complete(struct usb_ep *ep,
  156. struct usb_request *req)
  157. {
  158. struct diag_context *ctxt = ep->driver_data;
  159. struct diag_request *d_req = req->context;
  160. unsigned long flags;
  161.  
  162. ctxt->dpkts_tolaptop_pending--;
  163.  
  164. if (!req->status) {
  165. if ((req->length >= ep->maxpacket) &&
  166. ((req->length % ep->maxpacket) == 0)) {
  167. ctxt->dpkts_tolaptop_pending++;
  168. req->length = 0;
  169. d_req->actual = req->actual;
  170. d_req->status = req->status;
  171. /* Queue zero length packet */
  172. usb_ep_queue(ctxt->in, req, GFP_ATOMIC);
  173. return;
  174. }
  175. }
  176.  
  177. spin_lock_irqsave(&ctxt->lock, flags);
  178. list_add_tail(&req->list, &ctxt->write_pool);
  179. if (req->length != 0) {
  180. d_req->actual = req->actual;
  181. d_req->status = req->status;
  182. }
  183. spin_unlock_irqrestore(&ctxt->lock, flags);
  184.  
  185. if (ctxt->ch.notify) {
  186. // zero_pky.patch by jagadish
  187. ctxt->qxdm_ops = 1;
  188. ctxt->ch.notify(ctxt->ch.priv, USB_DIAG_WRITE_DONE, d_req);
  189. }
  190.  
  191. }
  192.  
  193. static void diag_read_complete(struct usb_ep *ep,
  194. struct usb_request *req)
  195. {
  196. struct diag_context *ctxt = ep->driver_data;
  197. struct diag_request *d_req = req->context;
  198. unsigned long flags;
  199.  
  200. d_req->actual = req->actual;
  201. d_req->status = req->status;
  202.  
  203. spin_lock_irqsave(&ctxt->lock, flags);
  204. list_add_tail(&req->list, &ctxt->read_pool);
  205. spin_unlock_irqrestore(&ctxt->lock, flags);
  206.  
  207. ctxt->dpkts_tomodem++;
  208.  
  209. if (ctxt->ch.notify) {
  210. // zero_pky.patch by jagadish
  211. ctxt->qxdm_ops = 1;
  212. ctxt->ch.notify(ctxt->ch.priv, USB_DIAG_READ_DONE, d_req);
  213. }
  214.  
  215. }
  216.  
  217. /**
  218. * usb_diag_open() - Open a diag channel over USB
  219. * @name: Name of the channel
  220. * @priv: Private structure pointer which will be passed in notify()
  221. * @notify: Callback function to receive notifications
  222. *
  223. * This function iterates overs the available channels and returns
  224. * the channel handler if the name matches. The notify callback is called
  225. * for CONNECT, DISCONNECT, READ_DONE and WRITE_DONE events.
  226. *
  227. */
  228. struct usb_diag_ch *usb_diag_open(const char *name, void *priv,
  229. void (*notify)(void *, unsigned, struct diag_request *))
  230. {
  231. struct usb_diag_ch *ch;
  232. struct diag_context *ctxt;
  233. unsigned long flags;
  234. int found = 0;
  235.  
  236. spin_lock_irqsave(&ch_lock, flags);
  237. /* Check if we already have a channel with this name */
  238. list_for_each_entry(ch, &usb_diag_ch_list, list) {
  239. if (!strcmp(name, ch->name)) {
  240. found = 1;
  241. break;
  242. }
  243. }
  244. spin_unlock_irqrestore(&ch_lock, flags);
  245.  
  246. if (!found) {
  247. ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
  248. if (!ctxt)
  249. return ERR_PTR(-ENOMEM);
  250.  
  251. ch = &ctxt->ch;
  252. }
  253.  
  254. ch->name = name;
  255. ch->priv = priv;
  256. ch->notify = notify;
  257.  
  258. spin_lock_irqsave(&ch_lock, flags);
  259. list_add_tail(&ch->list, &usb_diag_ch_list);
  260. spin_unlock_irqrestore(&ch_lock, flags);
  261.  
  262. return ch;
  263. }
  264. EXPORT_SYMBOL(usb_diag_open);
  265.  
  266. /**
  267. * usb_diag_close() - Close a diag channel over USB
  268. * @ch: Channel handler
  269. *
  270. * This function closes the diag channel.
  271. *
  272. */
  273. void usb_diag_close(struct usb_diag_ch *ch)
  274. {
  275. struct diag_context *dev = container_of(ch, struct diag_context, ch);
  276. unsigned long flags;
  277.  
  278. spin_lock_irqsave(&ch_lock, flags);
  279. ch->priv = NULL;
  280. ch->notify = NULL;
  281. /* Free-up the resources if channel is no more active */
  282. if (!ch->priv_usb) {
  283. list_del(&ch->list);
  284. kfree(dev);
  285. }
  286.  
  287. spin_unlock_irqrestore(&ch_lock, flags);
  288. }
  289. EXPORT_SYMBOL(usb_diag_close);
  290.  
  291. /**
  292. * usb_diag_free_req() - Free USB requests
  293. * @ch: Channel handler
  294. *
  295. * This function free read and write USB requests for the interface
  296. * associated with this channel.
  297. *
  298. */
  299. void usb_diag_free_req(struct usb_diag_ch *ch)
  300. {
  301. struct diag_context *ctxt = ch->priv_usb;
  302. struct usb_request *req;
  303. struct list_head *act, *tmp;
  304.  
  305. if (!ctxt)
  306. return;
  307.  
  308. list_for_each_safe(act, tmp, &ctxt->write_pool) {
  309. req = list_entry(act, struct usb_request, list);
  310. list_del(&req->list);
  311. usb_ep_free_request(ctxt->in, req);
  312. }
  313.  
  314. list_for_each_safe(act, tmp, &ctxt->read_pool) {
  315. req = list_entry(act, struct usb_request, list);
  316. list_del(&req->list);
  317. usb_ep_free_request(ctxt->out, req);
  318. }
  319. }
  320. EXPORT_SYMBOL(usb_diag_free_req);
  321.  
  322. /**
  323. * usb_diag_alloc_req() - Allocate USB requests
  324. * @ch: Channel handler
  325. * @n_write: Number of requests for Tx
  326. * @n_read: Number of requests for Rx
  327. *
  328. * This function allocate read and write USB requests for the interface
  329. * associated with this channel. The actual buffer is not allocated.
  330. * The buffer is passed by diag char driver.
  331. *
  332. */
  333. int usb_diag_alloc_req(struct usb_diag_ch *ch, int n_write, int n_read)
  334. {
  335. struct diag_context *ctxt = ch->priv_usb;
  336. struct usb_request *req;
  337. int i;
  338.  
  339. if (!ctxt)
  340. return -ENODEV;
  341.  
  342. for (i = 0; i < n_write; i++) {
  343. req = usb_ep_alloc_request(ctxt->in, GFP_ATOMIC);
  344. if (!req)
  345. goto fail;
  346. req->complete = diag_write_complete;
  347. list_add_tail(&req->list, &ctxt->write_pool);
  348. }
  349.  
  350. for (i = 0; i < n_read; i++) {
  351. req = usb_ep_alloc_request(ctxt->out, GFP_ATOMIC);
  352. if (!req)
  353. goto fail;
  354. req->complete = diag_read_complete;
  355. list_add_tail(&req->list, &ctxt->read_pool);
  356. }
  357.  
  358. return 0;
  359.  
  360. fail:
  361. usb_diag_free_req(ch);
  362. return -ENOMEM;
  363.  
  364. }
  365. EXPORT_SYMBOL(usb_diag_alloc_req);
  366.  
  367. /**
  368. * usb_diag_read() - Read data from USB diag channel
  369. * @ch: Channel handler
  370. * @d_req: Diag request struct
  371. *
  372. * Enqueue a request on OUT endpoint of the interface corresponding to this
  373. * channel. This function returns proper error code when interface is not
  374. * in configured state, no Rx requests available and ep queue is failed.
  375. *
  376. * This function operates asynchronously. READ_DONE event is notified after
  377. * completion of OUT request.
  378. *
  379. */
  380. int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req)
  381. {
  382. struct diag_context *ctxt = ch->priv_usb;
  383. unsigned long flags;
  384. struct usb_request *req;
  385.  
  386. if (!ctxt)
  387. return -ENODEV;
  388.  
  389. spin_lock_irqsave(&ctxt->lock, flags);
  390.  
  391. if (!ctxt->configured) {
  392. spin_unlock_irqrestore(&ctxt->lock, flags);
  393. return -EIO;
  394. }
  395.  
  396. if (list_empty(&ctxt->read_pool)) {
  397. spin_unlock_irqrestore(&ctxt->lock, flags);
  398. ERROR(ctxt->cdev, "%s: no requests available\n", __func__);
  399. return -EAGAIN;
  400. }
  401.  
  402. req = list_first_entry(&ctxt->read_pool, struct usb_request, list);
  403. list_del(&req->list);
  404. spin_unlock_irqrestore(&ctxt->lock, flags);
  405.  
  406. req->buf = d_req->buf;
  407. req->length = d_req->length;
  408. req->context = d_req;
  409. if (usb_ep_queue(ctxt->out, req, GFP_ATOMIC)) {
  410. /* If error add the link to linked list again*/
  411. spin_lock_irqsave(&ctxt->lock, flags);
  412. list_add_tail(&req->list, &ctxt->read_pool);
  413. spin_unlock_irqrestore(&ctxt->lock, flags);
  414. ERROR(ctxt->cdev, "%s: cannot queue"
  415. " read request\n", __func__);
  416. return -EIO;
  417. }
  418.  
  419. return 0;
  420. }
  421. EXPORT_SYMBOL(usb_diag_read);
  422.  
  423. /**
  424. * usb_diag_write() - Write data from USB diag channel
  425. * @ch: Channel handler
  426. * @d_req: Diag request struct
  427. *
  428. * Enqueue a request on IN endpoint of the interface corresponding to this
  429. * channel. This function returns proper error code when interface is not
  430. * in configured state, no Tx requests available and ep queue is failed.
  431. *
  432. * This function operates asynchronously. WRITE_DONE event is notified after
  433. * completion of IN request.
  434. *
  435. */
  436. int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req)
  437. {
  438. struct diag_context *ctxt = ch->priv_usb;
  439. unsigned long flags;
  440. struct usb_request *req = NULL;
  441.  
  442. if (!ctxt)
  443. return -ENODEV;
  444.  
  445. spin_lock_irqsave(&ctxt->lock, flags);
  446.  
  447. if (!ctxt->configured) {
  448. spin_unlock_irqrestore(&ctxt->lock, flags);
  449. return -EIO;
  450. }
  451.  
  452. if (list_empty(&ctxt->write_pool)) {
  453. spin_unlock_irqrestore(&ctxt->lock, flags);
  454. ERROR(ctxt->cdev, "%s: no requests available\n", __func__);
  455. return -EAGAIN;
  456. }
  457.  
  458. req = list_first_entry(&ctxt->write_pool, struct usb_request, list);
  459. list_del(&req->list);
  460. spin_unlock_irqrestore(&ctxt->lock, flags);
  461.  
  462. req->buf = d_req->buf;
  463. req->length = d_req->length;
  464. req->context = d_req;
  465. if (usb_ep_queue(ctxt->in, req, GFP_ATOMIC)) {
  466. /* If error add the link to linked list again*/
  467. spin_lock_irqsave(&ctxt->lock, flags);
  468. list_add_tail(&req->list, &ctxt->write_pool);
  469. spin_unlock_irqrestore(&ctxt->lock, flags);
  470. ERROR(ctxt->cdev, "%s: cannot queue"
  471. " read request\n", __func__);
  472. return -EIO;
  473. }
  474.  
  475. ctxt->dpkts_tolaptop++;
  476. ctxt->dpkts_tolaptop_pending++;
  477.  
  478. return 0;
  479. }
  480. EXPORT_SYMBOL(usb_diag_write);
  481.  
  482. static void diag_function_disable(struct usb_function *f)
  483. {
  484. struct diag_context *dev = func_to_diag(f);
  485. unsigned long flags;
  486.  
  487. DBG(dev->cdev, "diag_function_disable\n");
  488.  
  489. spin_lock_irqsave(&dev->lock, flags);
  490. dev->configured = 0;
  491. spin_unlock_irqrestore(&dev->lock, flags);
  492.  
  493. // zero_pky.patch by jagadish
  494. if (dev->ch.notify) {
  495. if (dev->qxdm_ops)
  496. dev->ch.notify(dev->ch.priv, USB_DIAG_QXDM_DISCONNECT, NULL);
  497. else
  498. dev->ch.notify(dev->ch.priv, USB_DIAG_DISCONNECT, NULL);
  499. dev->qxdm_ops = 0;
  500. }
  501.  
  502.  
  503. usb_ep_disable(dev->in);
  504. dev->in->driver_data = NULL;
  505.  
  506. usb_ep_disable(dev->out);
  507. dev->out->driver_data = NULL;
  508.  
  509. }
  510.  
  511. static int diag_function_set_alt(struct usb_function *f,
  512. unsigned intf, unsigned alt)
  513. {
  514. struct diag_context *dev = func_to_diag(f);
  515. struct usb_composite_dev *cdev = f->config->cdev;
  516. unsigned long flags;
  517. int rc = 0;
  518.  
  519. dev->in_desc = ep_choose(cdev->gadget,
  520. (struct usb_endpoint_descriptor *)f->hs_descriptors[1],
  521. (struct usb_endpoint_descriptor *)f->descriptors[1]);
  522. dev->out_desc = ep_choose(cdev->gadget,
  523. (struct usb_endpoint_descriptor *)f->hs_descriptors[2],
  524. (struct usb_endpoint_descriptor *)f->descriptors[2]);
  525. dev->in->driver_data = dev;
  526. rc = usb_ep_enable(dev->in, dev->in_desc);
  527. if (rc) {
  528. ERROR(dev->cdev, "can't enable %s, result %d\n",
  529. dev->in->name, rc);
  530. return rc;
  531. }
  532. dev->out->driver_data = dev;
  533. rc = usb_ep_enable(dev->out, dev->out_desc);
  534. if (rc) {
  535. ERROR(dev->cdev, "can't enable %s, result %d\n",
  536. dev->out->name, rc);
  537. usb_ep_disable(dev->in);
  538. return rc;
  539. }
  540. schedule_work(&dev->config_work);
  541.  
  542. dev->dpkts_tolaptop = 0;
  543. dev->dpkts_tomodem = 0;
  544. dev->dpkts_tolaptop_pending = 0;
  545.  
  546. spin_lock_irqsave(&dev->lock, flags);
  547. dev->configured = 1;
  548. spin_unlock_irqrestore(&dev->lock, flags);
  549.  
  550. return rc;
  551. }
  552.  
  553. static void diag_function_unbind(struct usb_configuration *c,
  554. struct usb_function *f)
  555. {
  556. struct diag_context *ctxt = func_to_diag(f);
  557.  
  558. if (gadget_is_dualspeed(c->cdev->gadget))
  559. usb_free_descriptors(f->hs_descriptors);
  560.  
  561. usb_free_descriptors(f->descriptors);
  562. ctxt->ch.priv_usb = NULL;
  563. }
  564.  
  565. static int diag_function_bind(struct usb_configuration *c,
  566. struct usb_function *f)
  567. {
  568. struct usb_composite_dev *cdev = c->cdev;
  569. struct diag_context *ctxt = func_to_diag(f);
  570. struct usb_ep *ep;
  571. int status = -ENODEV;
  572.  
  573. intf_desc.bInterfaceNumber = usb_interface_id(c, f);
  574.  
  575. ep = usb_ep_autoconfig(cdev->gadget, &fs_bulk_in_desc);
  576. if (!ep)
  577. goto fail;
  578. ctxt->in = ep;
  579. ep->driver_data = ctxt;
  580.  
  581. ep = usb_ep_autoconfig(cdev->gadget, &fs_bulk_out_desc);
  582. if (!ep)
  583. goto fail;
  584. ctxt->out = ep;
  585. ep->driver_data = ctxt;
  586.  
  587. /* copy descriptors, and track endpoint copies */
  588. f->descriptors = usb_copy_descriptors(fs_diag_desc);
  589. if (!f->descriptors)
  590. goto fail;
  591.  
  592. if (gadget_is_dualspeed(c->cdev->gadget)) {
  593. hs_bulk_in_desc.bEndpointAddress =
  594. fs_bulk_in_desc.bEndpointAddress;
  595. hs_bulk_out_desc.bEndpointAddress =
  596. fs_bulk_out_desc.bEndpointAddress;
  597.  
  598. /* copy descriptors, and track endpoint copies */
  599. f->hs_descriptors = usb_copy_descriptors(hs_diag_desc);
  600. }
  601. return 0;
  602. fail:
  603. if (ctxt->out)
  604. ctxt->out->driver_data = NULL;
  605. if (ctxt->in)
  606. ctxt->in->driver_data = NULL;
  607. return status;
  608.  
  609. }
  610.  
  611. int diag_function_add(struct usb_configuration *c, const char *name,
  612. int (*update_pid)(uint32_t, const char *))
  613. {
  614. struct diag_context *dev;
  615. struct usb_diag_ch *_ch;
  616. int found = 0, ret;
  617.  
  618. DBG(c->cdev, "diag_function_add\n");
  619.  
  620. list_for_each_entry(_ch, &usb_diag_ch_list, list) {
  621. if (!strcmp(name, _ch->name)) {
  622. found = 1;
  623. break;
  624. }
  625. }
  626. if (!found) {
  627. ERROR(c->cdev, "usb: unable to get diag usb channel\n");
  628.  
  629. return -ENODEV;
  630. }
  631.  
  632. dev = container_of(_ch, struct diag_context, ch);
  633. /* claim the channel for this USB interface */
  634. _ch->priv_usb = dev;
  635.  
  636. dev->update_pid_and_serial_num = update_pid;
  637. dev->cdev = c->cdev;
  638. dev->function.name = _ch->name;
  639. dev->function.descriptors = fs_diag_desc;
  640. dev->function.hs_descriptors = hs_diag_desc;
  641. dev->function.bind = diag_function_bind;
  642. dev->function.unbind = diag_function_unbind;
  643. dev->function.set_alt = diag_function_set_alt;
  644. dev->function.disable = diag_function_disable;
  645. spin_lock_init(&dev->lock);
  646. INIT_LIST_HEAD(&dev->read_pool);
  647. INIT_LIST_HEAD(&dev->write_pool);
  648. INIT_WORK(&dev->config_work, usb_config_work_func);
  649.  
  650. ret = usb_add_function(c, &dev->function);
  651. if (ret) {
  652. INFO(c->cdev, "usb_add_function failed\n");
  653. _ch->priv_usb = NULL;
  654. }
  655.  
  656. return ret;
  657. }
  658.  
  659.  
  660. #if defined(CONFIG_DEBUG_FS)
  661. static char debug_buffer[PAGE_SIZE];
  662.  
  663. static ssize_t debug_read_stats(struct file *file, char __user *ubuf,
  664. size_t count, loff_t *ppos)
  665. {
  666. char *buf = debug_buffer;
  667. int temp = 0;
  668. struct usb_diag_ch *ch;
  669.  
  670. list_for_each_entry(ch, &usb_diag_ch_list, list) {
  671. struct diag_context *ctxt;
  672.  
  673. ctxt = ch->priv_usb;
  674.  
  675. temp += scnprintf(buf + temp, PAGE_SIZE - temp,
  676. "---Name: %s---\n"
  677. "endpoints: %s, %s\n"
  678. "dpkts_tolaptop: %lu\n"
  679. "dpkts_tomodem: %lu\n"
  680. "pkts_tolaptop_pending: %u\n",
  681. ch->name,
  682. ctxt->in->name, ctxt->out->name,
  683. ctxt->dpkts_tolaptop,
  684. ctxt->dpkts_tomodem,
  685. ctxt->dpkts_tolaptop_pending);
  686. }
  687.  
  688. return simple_read_from_buffer(ubuf, count, ppos, buf, temp);
  689. }
  690.  
  691. static ssize_t debug_reset_stats(struct file *file, const char __user *buf,
  692. size_t count, loff_t *ppos)
  693. {
  694. struct usb_diag_ch *ch;
  695.  
  696. list_for_each_entry(ch, &usb_diag_ch_list, list) {
  697. struct diag_context *ctxt;
  698.  
  699. ctxt = ch->priv_usb;
  700.  
  701. ctxt->dpkts_tolaptop = 0;
  702. ctxt->dpkts_tomodem = 0;
  703. ctxt->dpkts_tolaptop_pending = 0;
  704. }
  705.  
  706. return count;
  707. }
  708.  
  709. static int debug_open(struct inode *inode, struct file *file)
  710. {
  711. return 0;
  712. }
  713.  
  714. static const struct file_operations debug_fdiag_ops = {
  715. .open = debug_open,
  716. .read = debug_read_stats,
  717. .write = debug_reset_stats,
  718. };
  719.  
  720. struct dentry *dent_diag;
  721. static void fdiag_debugfs_init(void)
  722. {
  723. dent_diag = debugfs_create_dir("usb_diag", 0);
  724. if (IS_ERR(dent_diag))
  725. return;
  726.  
  727. debugfs_create_file("status", 0444, dent_diag, 0, &debug_fdiag_ops);
  728. }
  729. #else
  730. static void fdiag_debugfs_init(void)
  731. {
  732. return;
  733. }
  734. #endif
  735.  
  736. static void diag_cleanup(void)
  737. {
  738. struct diag_context *dev;
  739. struct list_head *act, *tmp;
  740. struct usb_diag_ch *_ch;
  741. unsigned long flags;
  742.  
  743. debugfs_remove_recursive(dent_diag);
  744.  
  745. list_for_each_safe(act, tmp, &usb_diag_ch_list) {
  746. _ch = list_entry(act, struct usb_diag_ch, list);
  747. dev = container_of(_ch, struct diag_context, ch);
  748.  
  749. spin_lock_irqsave(&ch_lock, flags);
  750. /* Free if diagchar is not using the channel anymore */
  751. if (!_ch->priv) {
  752. list_del(&_ch->list);
  753. kfree(dev);
  754. }
  755. spin_unlock_irqrestore(&ch_lock, flags);
  756. }
  757. }
  758.  
  759. static int diag_setup(void)
  760. {
  761. fdiag_debugfs_init();
  762.  
  763. return 0;
  764. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement