| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * firmware_sample_driver.c - | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-06-04 18:45:44 +02:00
										 |  |  |  * Copyright (c) 2003 Manuel Estrada Sainz | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Sample code on how to use request_firmware() from drivers. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/device.h>
 | 
					
						
							| 
									
										
										
										
											2005-10-30 15:03:48 -08:00
										 |  |  | #include <linux/string.h>
 | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | #include <linux/firmware.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct device ghost_device = { | 
					
						
							|  |  |  | 	.bus_id    = "ghost0", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sample_firmware_load(char *firmware, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u8 buf[size+1]; | 
					
						
							|  |  |  | 	memcpy(buf, firmware, size); | 
					
						
							|  |  |  | 	buf[size] = '\0'; | 
					
						
							| 
									
										
										
										
											2005-09-08 08:55:53 +02:00
										 |  |  | 	printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sample_probe_default(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* uses the default method to get the firmware */ | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 	const struct firmware *fw_entry; | 
					
						
							|  |  |  | 	int retval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	printk(KERN_INFO "firmware_sample_driver: " | 
					
						
							|  |  |  | 		"a ghost device got inserted :)\n"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 	retval = request_firmware(&fw_entry, "sample_driver_fw", &ghost_device); | 
					
						
							|  |  |  | 	if (retval) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		printk(KERN_ERR | 
					
						
							|  |  |  | 		       "firmware_sample_driver: Firmware not available\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-20 13:20:50 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	sample_firmware_load(fw_entry->data, fw_entry->size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	release_firmware(fw_entry); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* finish setting up the device */ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | static void sample_probe_specific(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 	int retval; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	/* Uses some specific hotplug support to get the firmware from
 | 
					
						
							|  |  |  | 	 * userspace  directly into the hardware, or via some sysfs file */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* NOTE: This currently doesn't work */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 	printk(KERN_INFO "firmware_sample_driver: " | 
					
						
							|  |  |  | 		"a ghost device got inserted :)\n"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 	retval = request_firmware(NULL, "sample_driver_fw", &ghost_device); | 
					
						
							|  |  |  | 	if (retval) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		printk(KERN_ERR | 
					
						
							|  |  |  | 		       "firmware_sample_driver: Firmware load failed\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-20 13:20:50 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	/* request_firmware blocks until userspace finished, so at
 | 
					
						
							|  |  |  | 	 * this point the firmware should be already in the device */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* finish setting up the device */ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-04-21 16:36:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | static void sample_probe_async_cont(const struct firmware *fw, void *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 	if (!fw) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		printk(KERN_ERR | 
					
						
							|  |  |  | 		       "firmware_sample_driver: firmware load failed\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-08 08:55:53 +02:00
										 |  |  | 	printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n", | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	       (char *)context); | 
					
						
							|  |  |  | 	sample_firmware_load(fw->data, fw->size); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | static void sample_probe_async(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Let's say that I can't sleep */ | 
					
						
							|  |  |  | 	int error; | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 	error = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 
					
						
							|  |  |  | 					"sample_driver_fw", &ghost_device, | 
					
						
							|  |  |  | 					"my device pointer", | 
					
						
							|  |  |  | 					sample_probe_async_cont); | 
					
						
							|  |  |  | 	if (error) | 
					
						
							|  |  |  | 		printk(KERN_ERR "firmware_sample_driver:" | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		       " request_firmware_nowait failed\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-06 14:40:52 -08:00
										 |  |  | static int __init sample_init(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	device_initialize(&ghost_device); | 
					
						
							|  |  |  | 	/* since there is no real hardware insertion I just call the
 | 
					
						
							|  |  |  | 	 * sample probe functions here */ | 
					
						
							|  |  |  | 	sample_probe_specific(); | 
					
						
							|  |  |  | 	sample_probe_default(); | 
					
						
							|  |  |  | 	sample_probe_async(); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | static void __exit sample_exit(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-20 16:07:07 -08:00
										 |  |  | module_init(sample_init); | 
					
						
							|  |  |  | module_exit(sample_exit); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); |