Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/wireless/purelifi/plfxlc/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  firmware.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2021 pureLiFi
 */


#include <linux/firmware.h>
#include <linux/bitrev.h>

#include "mac.h"
#include "usb.h"

static int send_vendor_request(struct usb_device *udev, int request,
          unsigned char *buffer, int buffer_size)
{
 return usb_control_msg(udev,
          usb_rcvctrlpipe(udev, 0),
          request, 0xC0, 0, 0,
          buffer, buffer_size, PLF_USB_TIMEOUT);
}

static int send_vendor_command(struct usb_device *udev, int request,
          unsigned char *buffer, int buffer_size)
{
 return usb_control_msg(udev,
          usb_sndctrlpipe(udev, 0),
          request, USB_TYPE_VENDOR /*0x40*/, 0, 0,
          buffer, buffer_size, PLF_USB_TIMEOUT);
}

int plfxlc_download_fpga(struct usb_interface *intf)
{
 struct usb_device *udev = interface_to_usbdev(intf);
 unsigned char *fpga_dmabuff = NULL;
 const struct firmware *fw = NULL;
 int blk_tran_len = PLF_BULK_TLEN;
 unsigned char *fw_data;
 const char *fw_name;
 int r, actual_length;
 int fw_data_i = 0;

 if ((le16_to_cpu(udev->descriptor.idVendor) ==
    PURELIFI_X_VENDOR_ID_0) &&
     (le16_to_cpu(udev->descriptor.idProduct) ==
    PURELIFI_X_PRODUCT_ID_0)) {
  fw_name = "plfxlc/lifi-x.bin";
  dev_dbg(&intf->dev, "bin file for X selected\n");

 } else if ((le16_to_cpu(udev->descriptor.idVendor)) ==
     PURELIFI_XC_VENDOR_ID_0 &&
     (le16_to_cpu(udev->descriptor.idProduct) ==
     PURELIFI_XC_PRODUCT_ID_0)) {
  fw_name = "plfxlc/lifi-xc.bin";
  dev_dbg(&intf->dev, "bin file for XC selected\n");

 } else {
  r = -EINVAL;
  goto error;
 }

 r = request_firmware(&fw, fw_name, &intf->dev);
 if (r) {
  dev_err(&intf->dev, "request_firmware failed (%d)\n", r);
  goto error;
 }
 fpga_dmabuff = kmalloc(PLF_FPGA_STATUS_LEN, GFP_KERNEL);

 if (!fpga_dmabuff) {
  r = -ENOMEM;
  goto error_free_fw;
 }
 send_vendor_request(udev, PLF_VNDR_FPGA_SET_REQ,
       fpga_dmabuff, PLF_FPGA_STATUS_LEN);

 send_vendor_command(udev, PLF_VNDR_FPGA_SET_CMD, NULL, 0);

 if (fpga_dmabuff[0] != PLF_FPGA_MG) {
  dev_err(&intf->dev, "fpga_dmabuff[0] is wrong\n");
  r = -EINVAL;
  goto error_free_fw;
 }

 for (fw_data_i = 0; fw_data_i < fw->size;) {
  int tbuf_idx;

  if ((fw->size - fw_data_i) < blk_tran_len)
   blk_tran_len = fw->size - fw_data_i;

  fw_data = kmemdup(&fw->data[fw_data_i], blk_tran_len,
      GFP_KERNEL);
  if (!fw_data) {
   r = -ENOMEM;
   goto error_free_fw;
  }

  for (tbuf_idx = 0; tbuf_idx < blk_tran_len; tbuf_idx++) {
   /* u8 bit reverse */
   fw_data[tbuf_idx] = bitrev8(fw_data[tbuf_idx]);
  }
  r = usb_bulk_msg(udev,
     usb_sndbulkpipe(interface_to_usbdev(intf),
       fpga_dmabuff[0] & 0xff),
     fw_data,
     blk_tran_len,
     &actual_length,
     2 * PLF_USB_TIMEOUT);

  if (r)
   dev_err(&intf->dev, "Bulk msg failed (%d)\n", r);

  kfree(fw_data);
  fw_data_i += blk_tran_len;
 }

 kfree(fpga_dmabuff);
 fpga_dmabuff = kmalloc(PLF_FPGA_STATE_LEN, GFP_KERNEL);
 if (!fpga_dmabuff) {
  r = -ENOMEM;
  goto error_free_fw;
 }
 memset(fpga_dmabuff, 0xff, PLF_FPGA_STATE_LEN);

 send_vendor_request(udev, PLF_VNDR_FPGA_STATE_REQ, fpga_dmabuff,
       PLF_FPGA_STATE_LEN);

 dev_dbg(&intf->dev, "%*ph\n", 8, fpga_dmabuff);

 if (fpga_dmabuff[0] != 0) {
  r = -EINVAL;
  goto error_free_fw;
 }

 send_vendor_command(udev, PLF_VNDR_FPGA_STATE_CMD, NULL, 0);

 msleep(PLF_MSLEEP_TIME);

error_free_fw:
 kfree(fpga_dmabuff);
 release_firmware(fw);
error:
 return r;
}

int plfxlc_download_xl_firmware(struct usb_interface *intf)
{
 struct usb_device *udev = interface_to_usbdev(intf);
 const struct firmware *fwp = NULL;
 struct plfxlc_firmware_file file = {0};
 const char *fw_pack;
 int s, r;
 u8 *buf;
 u32 i;

 r = send_vendor_command(udev, PLF_VNDR_XL_FW_CMD, NULL, 0);
 msleep(PLF_MSLEEP_TIME);

 if (r) {
  dev_err(&intf->dev, "vendor command failed (%d)\n", r);
  return -EINVAL;
 }
 /* Code for single pack file download */

 fw_pack = "plfxlc/lifi-xl.bin";

 r = request_firmware(&fwp, fw_pack, &intf->dev);
 if (r) {
  dev_err(&intf->dev, "Request_firmware failed (%d)\n", r);
  return -EINVAL;
 }
 file.total_files = get_unaligned_le32(&fwp->data[0]);
 file.total_size = get_unaligned_le32(&fwp->size);

 dev_dbg(&intf->dev, "XL Firmware (%d, %d)\n",
  file.total_files, file.total_size);

 buf = kzalloc(PLF_XL_BUF_LEN, GFP_KERNEL);
 if (!buf) {
  release_firmware(fwp);
  return -ENOMEM;
 }

 if (file.total_files > 10) {
  dev_err(&intf->dev, "Too many files (%d)\n", file.total_files);
  release_firmware(fwp);
  kfree(buf);
  return -EINVAL;
 }

 /* Download firmware files in multiple steps */
 for (s = 0; s < file.total_files; s++) {
  buf[0] = s;
  r = send_vendor_command(udev, PLF_VNDR_XL_FILE_CMD, buf,
     PLF_XL_BUF_LEN);

  if (s < file.total_files - 1)
   file.size = get_unaligned_le32(&fwp->data[4 + ((s + 1) * 4)])
        - get_unaligned_le32(&fwp->data[4 + (s) * 4]);
  else
   file.size = file.total_size -
        get_unaligned_le32(&fwp->data[4 + (s) * 4]);

  if (file.size > file.total_size || file.size > 60000) {
   dev_err(&intf->dev, "File size is too large (%d)\n", file.size);
   break;
  }

  file.start_addr = get_unaligned_le32(&fwp->data[4 + (s * 4)]);

  if (file.size % PLF_XL_BUF_LEN && s < 2)
   file.size += PLF_XL_BUF_LEN - file.size % PLF_XL_BUF_LEN;

  file.control_packets = file.size / PLF_XL_BUF_LEN;

  for (i = 0; i < file.control_packets; i++) {
   memcpy(buf,
          &fwp->data[file.start_addr + (i * PLF_XL_BUF_LEN)],
          PLF_XL_BUF_LEN);
   r = send_vendor_command(udev, PLF_VNDR_XL_DATA_CMD, buf,
      PLF_XL_BUF_LEN);
  }
  dev_dbg(&intf->dev, "fw-dw step=%d,r=%d size=%d\n", s, r,
   file.size);
 }
 release_firmware(fwp);
 kfree(buf);

 /* Code for single pack file download ends fw download finish */

 r = send_vendor_command(udev, PLF_VNDR_XL_EX_CMD, NULL, 0);
 dev_dbg(&intf->dev, "Download fpga (4) (%d)\n", r);

 return 0;
}

int plfxlc_upload_mac_and_serial(struct usb_interface *intf,
     unsigned char *hw_address,
     unsigned char *serial_number)
{
 struct usb_device *udev = interface_to_usbdev(intf);
 unsigned long long firmware_version;
 unsigned char *dma_buffer = NULL;

 dma_buffer = kmalloc(PLF_SERIAL_LEN, GFP_KERNEL);
 if (!dma_buffer)
  return -ENOMEM;

 BUILD_BUG_ON(ETH_ALEN > PLF_SERIAL_LEN);
 BUILD_BUG_ON(PLF_FW_VER_LEN > PLF_SERIAL_LEN);

 send_vendor_request(udev, PLF_MAC_VENDOR_REQUEST, dma_buffer,
       ETH_ALEN);

 memcpy(hw_address, dma_buffer, ETH_ALEN);

 send_vendor_request(udev, PLF_SERIAL_NUMBER_VENDOR_REQUEST,
       dma_buffer, PLF_SERIAL_LEN);

 send_vendor_request(udev, PLF_SERIAL_NUMBER_VENDOR_REQUEST,
       dma_buffer, PLF_SERIAL_LEN);

 memcpy(serial_number, dma_buffer, PLF_SERIAL_LEN);

 memset(dma_buffer, 0x00, PLF_SERIAL_LEN);

 send_vendor_request(udev, PLF_FIRMWARE_VERSION_VENDOR_REQUEST,
       (unsigned char *)dma_buffer, PLF_FW_VER_LEN);

 memcpy(&firmware_version, dma_buffer, PLF_FW_VER_LEN);

 dev_info(&intf->dev, "Firmware Version: %llu\n", firmware_version);
 kfree(dma_buffer);

 dev_dbg(&intf->dev, "Mac: %pM\n", hw_address);

 return 0;
}


Messung V0.5
C=96 H=86 G=90

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.