int sipc4_tx(struct sipc4_tx_data *data) { struct sk_buff *skb = data->skb; struct phonethdr *ph; unsigned int format; int err; if (!skb) return -EINVAL; if (skb->protocol == htons(ETH_P_PHONET)) { ph = pn_hdr(skb); data->res = ph->pn_res; /* Remove phonet header + address len(1byte)? */ skb_pull(skb, sizeof(struct phonethdr) + 1); } format = SIPC4_FORMAT(data->res); switch (format) { case SIPC4_FMT: err = sipc4_fmt_tx(data); break; case SIPC4_RAW: err = sipc4_raw_tx(data); break; case SIPC4_RFS: err = sipc4_rfs_tx(data); break; default: err = -EINVAL; break; } return err; }
static int usbsvn_write(struct net_device *dev, struct sipc4_tx_data *tx_data) { struct usbsvn *svn = netdev_priv(dev); struct sk_buff *skb; struct usbsvn_devdata *devdata; struct urb *req; int dev_id; int err; if (!svn->usbdev) return -1; /*hold on active mode until xmit*/ usb_mark_last_busy(svn->usbdev); wake_lock_pm(svn); err = usbsvn_initiated_resume(dev); if (err < 0) { printk(KERN_ERR "%s: usbsvn_initated_resume fail\n", __func__); goto exit; } skb = tx_data->skb; dev_id = SIPC4_FORMAT(tx_data->res); devdata = &svn->devdata[dev_id]; req = usb_alloc_urb(0, GFP_ATOMIC); if (!req) { printk(KERN_ERR "%s: can't get urb\n", __func__); err = -ENOMEM; goto exit; } usb_fill_bulk_urb(req, svn->usbdev, devdata->tx_pipe, skb->data, skb->len, tx_complete, skb); if (tx_debug) { char *buf = skb->data; int i; printk(KERN_ERR "[TX] dev_id: %d, size: %d\n", dev_id, skb->len); for (i = 0; i < skb->len; i++) printk(KERN_ERR "%x ", *(buf + i)); if (skb->len) printk(KERN_ERR "\n"); } req->transfer_flags = URB_ZERO_PACKET; err = usb_submit_urb(req, GFP_ATOMIC); if (err < 0) { printk(KERN_ERR "%s:usb_submit_urb fail\n", __func__); usb_free_urb(req); goto exit; } usb_mark_last_busy(svn->usbdev); if (dev_id == SIPC4_RAW) wake_lock_timeout_data(svn); exit: return err; }