root/drivers/media/usb/as102/as102_fw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. atohx
  2. parse_hex_line
  3. as102_firmware_upload
  4. as102_fw_upload

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Abilis Systems Single DVB-T Receiver
   4  * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
   5  * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/errno.h>
   9 #include <linux/ctype.h>
  10 #include <linux/delay.h>
  11 #include <linux/firmware.h>
  12 
  13 #include "as102_drv.h"
  14 #include "as102_fw.h"
  15 
  16 static const char as102_st_fw1[] = "as102_data1_st.hex";
  17 static const char as102_st_fw2[] = "as102_data2_st.hex";
  18 static const char as102_dt_fw1[] = "as102_data1_dt.hex";
  19 static const char as102_dt_fw2[] = "as102_data2_dt.hex";
  20 
  21 static unsigned char atohx(unsigned char *dst, char *src)
  22 {
  23         unsigned char value = 0;
  24 
  25         char msb = tolower(*src) - '0';
  26         char lsb = tolower(*(src + 1)) - '0';
  27 
  28         if (msb > 9)
  29                 msb -= 7;
  30         if (lsb > 9)
  31                 lsb -= 7;
  32 
  33         *dst = value = ((msb & 0xF) << 4) | (lsb & 0xF);
  34         return value;
  35 }
  36 
  37 /*
  38  * Parse INTEL HEX firmware file to extract address and data.
  39  */
  40 static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
  41                           unsigned char *data, int *dataLength,
  42                           unsigned char *addr_has_changed) {
  43 
  44         int count = 0;
  45         unsigned char *src, dst;
  46 
  47         if (*fw_data++ != ':') {
  48                 pr_err("invalid firmware file\n");
  49                 return -EFAULT;
  50         }
  51 
  52         /* locate end of line */
  53         for (src = fw_data; *src != '\n'; src += 2) {
  54                 atohx(&dst, src);
  55                 /* parse line to split addr / data */
  56                 switch (count) {
  57                 case 0:
  58                         *dataLength = dst;
  59                         break;
  60                 case 1:
  61                         addr[2] = dst;
  62                         break;
  63                 case 2:
  64                         addr[3] = dst;
  65                         break;
  66                 case 3:
  67                         /* check if data is an address */
  68                         if (dst == 0x04)
  69                                 *addr_has_changed = 1;
  70                         else
  71                                 *addr_has_changed = 0;
  72                         break;
  73                 case  4:
  74                 case  5:
  75                         if (*addr_has_changed)
  76                                 addr[(count - 4)] = dst;
  77                         else
  78                                 data[(count - 4)] = dst;
  79                         break;
  80                 default:
  81                         data[(count - 4)] = dst;
  82                         break;
  83                 }
  84                 count++;
  85         }
  86 
  87         /* return read value + ':' + '\n' */
  88         return (count * 2) + 2;
  89 }
  90 
  91 static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap,
  92                                  unsigned char *cmd,
  93                                  const struct firmware *firmware) {
  94 
  95         struct as10x_fw_pkt_t *fw_pkt;
  96         int total_read_bytes = 0, errno = 0;
  97         unsigned char addr_has_changed = 0;
  98 
  99         fw_pkt = kmalloc(sizeof(*fw_pkt), GFP_KERNEL);
 100         if (!fw_pkt)
 101                 return -ENOMEM;
 102 
 103 
 104         for (total_read_bytes = 0; total_read_bytes < firmware->size; ) {
 105                 int read_bytes = 0, data_len = 0;
 106 
 107                 /* parse intel hex line */
 108                 read_bytes = parse_hex_line(
 109                                 (u8 *) (firmware->data + total_read_bytes),
 110                                 fw_pkt->raw.address,
 111                                 fw_pkt->raw.data,
 112                                 &data_len,
 113                                 &addr_has_changed);
 114 
 115                 if (read_bytes <= 0)
 116                         goto error;
 117 
 118                 /* detect the end of file */
 119                 total_read_bytes += read_bytes;
 120                 if (total_read_bytes == firmware->size) {
 121                         fw_pkt->u.request[0] = 0x00;
 122                         fw_pkt->u.request[1] = 0x03;
 123 
 124                         /* send EOF command */
 125                         errno = bus_adap->ops->upload_fw_pkt(bus_adap,
 126                                                              (uint8_t *)
 127                                                              fw_pkt, 2, 0);
 128                         if (errno < 0)
 129                                 goto error;
 130                 } else {
 131                         if (!addr_has_changed) {
 132                                 /* prepare command to send */
 133                                 fw_pkt->u.request[0] = 0x00;
 134                                 fw_pkt->u.request[1] = 0x01;
 135 
 136                                 data_len += sizeof(fw_pkt->u.request);
 137                                 data_len += sizeof(fw_pkt->raw.address);
 138 
 139                                 /* send cmd to device */
 140                                 errno = bus_adap->ops->upload_fw_pkt(bus_adap,
 141                                                                      (uint8_t *)
 142                                                                      fw_pkt,
 143                                                                      data_len,
 144                                                                      0);
 145                                 if (errno < 0)
 146                                         goto error;
 147                         }
 148                 }
 149         }
 150 error:
 151         kfree(fw_pkt);
 152         return (errno == 0) ? total_read_bytes : errno;
 153 }
 154 
 155 int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
 156 {
 157         int errno = -EFAULT;
 158         const struct firmware *firmware = NULL;
 159         unsigned char *cmd_buf = NULL;
 160         const char *fw1, *fw2;
 161         struct usb_device *dev = bus_adap->usb_dev;
 162 
 163         /* select fw file to upload */
 164         if (dual_tuner) {
 165                 fw1 = as102_dt_fw1;
 166                 fw2 = as102_dt_fw2;
 167         } else {
 168                 fw1 = as102_st_fw1;
 169                 fw2 = as102_st_fw2;
 170         }
 171 
 172         /* allocate buffer to store firmware upload command and data */
 173         cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL);
 174         if (cmd_buf == NULL) {
 175                 errno = -ENOMEM;
 176                 goto error;
 177         }
 178 
 179         /* request kernel to locate firmware file: part1 */
 180         errno = request_firmware(&firmware, fw1, &dev->dev);
 181         if (errno < 0) {
 182                 pr_err("%s: unable to locate firmware file: %s\n",
 183                        DRIVER_NAME, fw1);
 184                 goto error;
 185         }
 186 
 187         /* initiate firmware upload */
 188         errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
 189         if (errno < 0) {
 190                 pr_err("%s: error during firmware upload part1\n",
 191                        DRIVER_NAME);
 192                 goto error;
 193         }
 194 
 195         pr_info("%s: firmware: %s loaded with success\n",
 196                 DRIVER_NAME, fw1);
 197         release_firmware(firmware);
 198         firmware = NULL;
 199 
 200         /* wait for boot to complete */
 201         mdelay(100);
 202 
 203         /* request kernel to locate firmware file: part2 */
 204         errno = request_firmware(&firmware, fw2, &dev->dev);
 205         if (errno < 0) {
 206                 pr_err("%s: unable to locate firmware file: %s\n",
 207                        DRIVER_NAME, fw2);
 208                 goto error;
 209         }
 210 
 211         /* initiate firmware upload */
 212         errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
 213         if (errno < 0) {
 214                 pr_err("%s: error during firmware upload part2\n",
 215                        DRIVER_NAME);
 216                 goto error;
 217         }
 218 
 219         pr_info("%s: firmware: %s loaded with success\n",
 220                 DRIVER_NAME, fw2);
 221 error:
 222         kfree(cmd_buf);
 223         release_firmware(firmware);
 224 
 225         return errno;
 226 }

/* [<][>][^][v][top][bottom][index][help] */