rt2x00firmware.c revision 811aa9cad1bd927999888ab56ed9592519d2fef6
1/* 2 Copyright (C) 2004 - 2008 rt2x00 SourceForge Project 3 <http://rt2x00.serialmonkey.com> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the 17 Free Software Foundation, Inc., 18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 21/* 22 Module: rt2x00lib 23 Abstract: rt2x00 firmware loading routines. 24 */ 25 26#include <linux/crc-itu-t.h> 27#include <linux/kernel.h> 28#include <linux/module.h> 29 30#include "rt2x00.h" 31#include "rt2x00lib.h" 32 33static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) 34{ 35 struct device *device = wiphy_dev(rt2x00dev->hw->wiphy); 36 const struct firmware *fw; 37 char *fw_name; 38 int retval; 39 u16 crc; 40 u16 tmp; 41 42 /* 43 * Read correct firmware from harddisk. 44 */ 45 fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev); 46 if (!fw_name) { 47 ERROR(rt2x00dev, 48 "Invalid firmware filename.\n" 49 "Please file bug report to %s.\n", DRV_PROJECT); 50 return -EINVAL; 51 } 52 53 INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name); 54 55 retval = request_firmware(&fw, fw_name, device); 56 if (retval) { 57 ERROR(rt2x00dev, "Failed to request Firmware.\n"); 58 return retval; 59 } 60 61 if (!fw || !fw->size || !fw->data) { 62 ERROR(rt2x00dev, "Failed to read Firmware.\n"); 63 return -ENOENT; 64 } 65 66 /* 67 * Validate the firmware using 16 bit CRC. 68 * The last 2 bytes of the firmware are the CRC 69 * so substract those 2 bytes from the CRC checksum, 70 * and set those 2 bytes to 0 when calculating CRC. 71 */ 72 tmp = 0; 73 crc = crc_itu_t(0, fw->data, fw->size - 2); 74 crc = crc_itu_t(crc, (u8 *)&tmp, 2); 75 76 if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) { 77 ERROR(rt2x00dev, "Firmware CRC error.\n"); 78 retval = -ENOENT; 79 goto exit; 80 } 81 82 INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", 83 fw->data[fw->size - 4], fw->data[fw->size - 3]); 84 85 rt2x00dev->fw = fw; 86 87 return 0; 88 89exit: 90 release_firmware(fw); 91 92 return retval; 93} 94 95int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) 96{ 97 int retval; 98 99 if (!rt2x00dev->fw) { 100 retval = rt2x00lib_request_firmware(rt2x00dev); 101 if (retval) 102 return retval; 103 } 104 105 /* 106 * Send firmware to the device. 107 */ 108 retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev, 109 rt2x00dev->fw->data, 110 rt2x00dev->fw->size); 111 return retval; 112} 113 114void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev) 115{ 116 release_firmware(rt2x00dev->fw); 117 rt2x00dev->fw = NULL; 118} 119 120