static int sam4e_read_fw_version(struct sam4e_usb *dev) { struct sam4e_req *req; struct sam4e_resp *resp; struct sam4e_fw_resp *fw; int resp_size; int actual_length; int result; struct net_device *netdev; netdev = dev->netdev1; LOGNI("Querying firmware version"); req = kzalloc(sizeof(struct sam4e_req), GFP_KERNEL); if (req == NULL) return -ENOMEM; req->cmd = CMD_SYS_GET_FW_VERSION; req->len = sizeof(struct sam4e_req); req->seq = atomic_inc_return(&dev->msg_seq); result = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, BULK_OUT_EP), req, sizeof(struct sam4e_req), &actual_length, 1000); LOGNI("sent %x result %d, actual_length %d", req->cmd, result, actual_length); kfree(req); resp_size = sizeof(struct sam4e_resp) + sizeof(struct sam4e_fw_resp); resp = kzalloc(resp_size, GFP_KERNEL); if (resp == NULL) return -ENOMEM; result = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, BULK_IN_EP), resp, resp_size, &actual_length, 1000); LOGNI("rcv? result %d, actual_length %d", result, actual_length); if (result == 0 && actual_length == resp_size) { fw = (struct sam4e_fw_resp *)resp->data; LOGNI("data %x %d %d %d\n", resp->cmd, resp->len, resp->seq, resp->err); netdev_info(netdev, "sam4e fw %d.%d", fw->maj, fw->min); netdev_info(netdev, "sam4e fw string %s", fw->ver); } kfree(resp); return 0; }
static int sam4e_netdev_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { LOGNI("sam4e_netdev_do_ioctl %d", cmd); if (cmd == IOCTL_RELEASE_CAN_BUFFER) { LOGNI("IOCTL_RELEASE_CAN_BUFFER"); sam4e_send_release_can_buffer_cmd(netdev); } else if (cmd == IOCTL_ENABLE_BUFFERING) { LOGNI("IOCTL_ENABLE_BUFFERING"); sam4e_enable_buffering(netdev, ifr); } return 0; }
static int sam4e_enable_buffering(struct net_device *netdev, struct ifreq *ifr) { struct sam4e_enable_buffering *add_request; struct sam4e_enable_buffering *enable_buffering; struct urb *urb; struct sam4e_req *req; struct sam4e_usb_handle *sam4e_usb_hnd = netdev_priv(netdev); struct sam4e_usb *dev = sam4e_usb_hnd->sam4e_dev; size_t size = sizeof(struct sam4e_req) + sizeof(struct sam4e_enable_buffering); int result; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { netdev_err(netdev, "No memory left for URBs\n"); goto nomem; } req = usb_alloc_coherent(dev->udev, size, GFP_KERNEL, &urb->transfer_dma); if (!req) { netdev_err(netdev, "No memory left for USB buffer\n"); usb_free_urb(urb); goto nomem; } add_request = ifr->ifr_data; /* Fill message data */ req->cmd = CMD_CAN_ENABLE_BUFFERING; req->len = sizeof(struct sam4e_req) + sizeof(struct sam4e_enable_buffering); req->seq = atomic_inc_return(&dev->msg_seq); enable_buffering = (struct sam4e_enable_buffering *)&req->data; enable_buffering->can = add_request->can; enable_buffering->mid = add_request->mid; enable_buffering->mask = add_request->mask; LOGNI("sam4e_send_enable_buffering %d %x %x", enable_buffering->can, enable_buffering->mid, enable_buffering->mask); usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, BULK_OUT_EP), req, size, sam4e_usb_write_bulk_callback, netdev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->tx_submitted); result = usb_submit_urb(urb, GFP_KERNEL); if (unlikely(result)) { usb_unanchor_urb(urb); usb_free_coherent(dev->udev, size, req, urb->transfer_dma); } usb_free_urb(urb); return result; nomem: return -ENOMEM; }
NS_IMETHODIMP WebBrowserChrome::DestroyBrowserWindow() { LOGNI(); if (mIsModal) { ExitModalEventLoop(NS_OK); } return NS_ERROR_NOT_IMPLEMENTED; }
/* * set up mail box for can frames. */ static void setup_mailbox(u8 mailbox, u8 canid, u32 filter, u32 mid, struct usb_interface *intf, struct usb_device *udev, struct sam4e_usb *dev) { struct sam4e_req *req; struct sam4e_resp *resp; int actual_length; int result; req = kzalloc(sizeof(struct sam4e_req) + sizeof(struct sam4e_can_full_ts_read), GFP_KERNEL); if (req != 0) { struct sam4e_can_full_ts_read *cfr = (struct sam4e_can_full_ts_read *)&req->data; req->cmd = CMD_CAN_TS_FULL_READ; req->len = sizeof(struct sam4e_req) + sizeof(struct sam4e_can_full_ts_read); req->seq = atomic_inc_return(&dev->msg_seq); cfr->mailbox = mailbox; cfr->can = canid; /* Timestamping on */ cfr->ts_on = 1; cfr->mid = mid; cfr->filter = filter; result = usb_bulk_msg(udev, usb_sndbulkpipe(udev, BULK_OUT_EP), req, sizeof(struct sam4e_req) + sizeof(struct sam4e_can_full_ts_read), &actual_length, 1000); LOGNI("sent %x result %d, actual_length %d", req->cmd, result, actual_length); kfree(req); } resp = kzalloc(sizeof(struct sam4e_resp), GFP_KERNEL); result = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, BULK_IN_EP), resp, sizeof(struct sam4e_resp), &actual_length, 1000); LOGNI("rcv? result %d, actual_length %d", result, actual_length); if (result == 0 && DEBUG_SAM4E) { dev_info(&intf->dev, "data %x %d %d %d\n", resp->cmd, resp->len, resp->seq, resp->err); } kfree(resp); }
NS_IMETHODIMP WebBrowserChrome::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsresult aStatus, const PRUnichar* aMessage) { LOGNI(); return NS_OK; }
static int sam4e_netdev_close(struct net_device *netdev) { struct sam4e_usb_handle *sam4e_usb_hnd = netdev_priv(netdev); struct sam4e_usb *dev = sam4e_usb_hnd->sam4e_dev; LOGNI("sam4e_close"); /* Stop polling */ unlink_all_urbs(dev); netif_stop_queue(netdev); close_candev(netdev); return 0; }
static int sam4e_netdev_open(struct net_device *netdev) { int err; LOGNI("sam4e_open"); err = open_candev(netdev); if (err) return err; netif_start_queue(netdev); return 0; }
static void sam4e_usb_receive_frame(struct sam4e_usb *dev, struct sam4e_can_unsl_ts_receive *frame) { struct can_frame *cf; struct sk_buff *skb; struct skb_shared_hwtstamps *skt; struct timeval tv; static int msec; int i; if (frame->can == 0) skb = alloc_can_skb(dev->netdev1, &cf); else skb = alloc_can_skb(dev->netdev2, &cf); if (skb == NULL) { pr_err("skb failed..frame->can %d", frame->can); return; } LOGNI(" rcv frame %d %x %d %x %x %x %x %x %x %x %x\n", frame->ts, frame->mid, frame->dlc, frame->data[0], frame->data[1], frame->data[2], frame->data[3], frame->data[4], frame->data[5], frame->data[6], frame->data[7]); cf->can_id = le32_to_cpu(frame->mid); cf->can_dlc = get_can_dlc(frame->dlc); for (i = 0; i < cf->can_dlc; i++) cf->data[i] = frame->data[i]; msec = le32_to_cpu(frame->ts); tv.tv_sec = msec / 1000; tv.tv_usec = (msec - tv.tv_sec * 1000) * 1000; skt = skb_hwtstamps(skb); skt->hwtstamp = timeval_to_ktime(tv); LOGNI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); skb->tstamp = timeval_to_ktime(tv); netif_rx(skb); }
static void sam4e_process_response(struct sam4e_usb *dev, struct sam4e_resp *resp, int length) { LOGNI("<%x %2d [%d] %d buff:[%d]\n", resp->cmd, resp->len, resp->seq, resp->err, atomic_read(&dev->active_tx_urbs)); if (resp->cmd == CMD_CAN_TS_READ_ASYNC) { /* v1.3 of the firmware uses different frame structure for unsol messages. (the one without error code) */ struct sam4e_unsol_msg *msg = (struct sam4e_unsol_msg *)resp; /* v2.2 of the firmware supports TS_READ_ASYNC */ struct sam4e_can_unsl_ts_receive *frame = (struct sam4e_can_unsl_ts_receive *)&msg->data; if (msg->len > length) { LOGNI("process_response: Saving %d bytes of response\n", length); memcpy(dev->assembly_buffer, (char *)resp, length); dev->assembly_buffer_size = length; } else { sam4e_usb_receive_frame(dev, frame); } } else if (resp->cmd == CMD_CAN_FULL_WRITE) { atomic_dec(&dev->active_tx_urbs); if ((atomic_read(&dev->netif_queue_stop) == 1) && atomic_read(&dev->active_tx_urbs) < MAX_TX_URBS) { LOGNI("Waking up queue. (%d)\n", atomic_read(&dev->active_tx_urbs)); netif_wake_queue(dev->netdev1); netif_wake_queue(dev->netdev2); atomic_dec(&dev->netif_queue_stop); } } else if (resp->cmd == CMD_CAN_RELEASE_BUFFER) { LOGNI("Received CMD_CAN_RELEASE_BUFFER response\n"); } else if (resp->cmd == CMD_CAN_ENABLE_BUFFERING) { LOGNI("Received CMD_CAN_ENABLE_BUFFERING response\n"); } }
/* * called by the usb core when the device is removed from the system */ static void sam4e_usb_disconnect(struct usb_interface *intf) { struct sam4e_usb *dev; dev = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); if (dev) { LOGNI("Disconnect sam4e\n"); if (dev->netdev1) { unregister_netdev(dev->netdev1); free_candev(dev->netdev1); } if (dev->netdev2) { unregister_netdev(dev->netdev2); free_candev(dev->netdev2); } kfree(dev->assembly_buffer); unlink_all_urbs(dev); kfree(dev); } }
NS_IMETHODIMP WebBrowserChrome::SetStatus(uint32_t /* statusType*/, const PRUnichar* /*status*/) { LOGNI(); return NS_OK; }
static void sam4e_usb_read_bulk_callback(struct urb *urb) { struct sam4e_usb *dev = urb->context; int err, length_processed = 0; LOGNI("sam4e_usb_read_bulk_callback length: %d\n", urb->actual_length); switch (urb->status) { case 0: break; case -ENOENT: return; default: pr_err("Rx URB aborted (%d)\n", urb->status); goto resubmit_urb; } while (length_processed < urb->actual_length) { int length_left = urb->actual_length - length_processed; int length = 0; /* length of consumed chunk */ void *data; if (dev->assembly_buffer_size > 0) { struct sam4e_resp *resp; LOGNI("callback: Reassembling %d bytes of response\n", dev->assembly_buffer_size); memcpy(dev->assembly_buffer + dev->assembly_buffer_size, urb->transfer_buffer, 2); data = dev->assembly_buffer; resp = (struct sam4e_resp *)data; length = resp->len - dev->assembly_buffer_size; if (length > 0) { memcpy(dev->assembly_buffer + dev->assembly_buffer_size, urb->transfer_buffer, length); } length_left += dev->assembly_buffer_size; dev->assembly_buffer_size = 0; } else { struct sam4e_resp *resp; data = urb->transfer_buffer + length_processed; resp = (struct sam4e_resp *)data; length = resp->len; } LOGNI("processing. p %d -> l %d (t %d)\n", length_processed, length_left, urb->actual_length); length_processed += length; if (length_left >= sizeof(struct sam4e_resp)) { struct sam4e_resp *resp = (struct sam4e_resp *)data; if (resp->len < sizeof(struct sam4e_resp)) { LOGNI("Error resp->len is %d). Abort.\n", resp->len); break; } sam4e_process_response(dev, resp, length_left); } else if (length_left > 0) { /* Not full message. Store however much we have for later assembly */ LOGNI("callback: Storing %d bytes of response\n", length_left); memcpy(dev->assembly_buffer, data, length_left); dev->assembly_buffer_size = length_left; break; } else { break; } } if (urb->actual_length > length_processed) { LOGNI("Error length > length_processed: %d > %d (needed: %d)\n", urb->actual_length, length_processed, sizeof(struct sam4e_resp)); } resubmit_urb: LOGNI("Resubmitting Rx Urb\n"); usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, BULK_IN_EP), urb->transfer_buffer, RX_BUFFER_SIZE, sam4e_usb_read_bulk_callback, dev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { usb_unanchor_urb(urb); usb_free_coherent(dev->udev, RX_BUFFER_SIZE, urb->transfer_buffer, urb->transfer_dma); pr_err("Failed to resubmit Rx Urb: %d\n", err); } }
NS_IMETHODIMP WebBrowserChrome::ExitModalEventLoop(nsresult aStatus) { LOGNI("status: %x", aStatus); return NS_OK; }
NS_IMETHODIMP WebBrowserChrome::ShowAsModal() { LOGNI(); return NS_OK; }
NS_IMETHODIMP WebBrowserChrome::SizeBrowserTo(int32_t aCX, int32_t aCY) { LOGNI("sz[%i,%i]\n", aCX, aCY); return NS_OK; }
static netdev_tx_t sam4e_netdev_start_xmit( struct sk_buff *skb, struct net_device *netdev) { struct sam4e_req *req; struct usb_device *udev; struct sam4e_usb_handle *sam4e_usb_hnd = netdev_priv(netdev); struct sam4e_usb *dev = sam4e_usb_hnd->sam4e_dev; struct net_device_stats *stats = &netdev->stats; int result; struct can_frame *cf = (struct can_frame *)skb->data; struct urb *urb; size_t size = sizeof(struct sam4e_req) + sizeof(struct sam4e_can_full_write); struct sam4e_can_full_write *cfw; if (can_dropped_invalid_skb(netdev, skb)) { pr_err("Dropping invalid can frame"); return NETDEV_TX_OK; } udev = dev->udev; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { pr_err("No memory left for URBs\n"); goto nomem; } req = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma); if (!req) { pr_err("No memory left for USB buffer\n"); usb_free_urb(urb); goto nomem; } /* Fill message data */ cfw = (struct sam4e_can_full_write *)&req->data; req->cmd = CMD_CAN_FULL_WRITE; req->len = sizeof(struct sam4e_req) + sizeof(struct sam4e_can_full_write); req->seq = atomic_inc_return(&dev->msg_seq); cfw->can = sam4e_usb_hnd->owner_netdev_index; cfw->mailbox = 0; cfw->prio = 0; cfw->mid = cf->can_id; cfw->dlc = cf->can_dlc; memcpy(cfw->data, cf->data, 8); LOGNI(">%x %2d [%d] send frame [%d] %x %d %x %x %x %x %x %x %x %x\n", req->cmd, req->len, req->seq, atomic_read(&dev->active_tx_urbs), cfw->mid, cfw->dlc, cfw->data[0], cfw->data[1], cfw->data[2], cfw->data[3], cfw->data[4], cfw->data[5], cfw->data[6], cfw->data[7]); usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, BULK_OUT_EP), req, size, sam4e_usb_write_bulk_callback, netdev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->tx_submitted); atomic_inc(&dev->active_tx_urbs); result = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(result)) { usb_unanchor_urb(urb); usb_free_coherent(dev->udev, size, req, urb->transfer_dma); dev_kfree_skb(skb); atomic_dec(&dev->active_tx_urbs); if (result == -ENODEV) { netif_device_detach(netdev); } else { pr_err("failed tx_urb %d\n", result); stats->tx_dropped++; } } else { /* Put on hold tx path */ if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS) { LOGNI("Too many outstanding requests (%d). Stop queue", atomic_read(&dev->active_tx_urbs)); atomic_inc(&dev->netif_queue_stop); if (dev->netdev1) netif_stop_queue(dev->netdev1); if (dev->netdev2) netif_stop_queue(dev->netdev2); } } dev_kfree_skb(skb); usb_free_urb(urb); return NETDEV_TX_OK; nomem: dev_kfree_skb(skb); stats->tx_dropped++; return NETDEV_TX_OK; }