2005-10-06 13:22:17 +10:00
# include <linux/string.h>
# include <linux/kernel.h>
2007-05-01 16:40:36 +10:00
# include <linux/of.h>
2005-10-06 13:22:17 +10:00
# include <linux/init.h>
# include <linux/module.h>
# include <linux/mod_devicetable.h>
2005-10-31 13:57:01 +11:00
# include <linux/slab.h>
2005-10-06 13:22:17 +10:00
# include <asm/errno.h>
# include <asm/of_device.h>
2007-05-07 01:38:46 +10:00
ssize_t of_device_get_modalias ( struct of_device * ofdev ,
char * str , ssize_t len )
2007-02-12 23:13:25 +01:00
{
const char * compat ;
int cplen , i ;
ssize_t tsize , csize , repend ;
/* Name & Type */
csize = snprintf ( str , len , " of:N%sT%s " ,
ofdev - > node - > name , ofdev - > node - > type ) ;
/* Get compatible property if any */
2007-04-13 17:14:22 +10:00
compat = of_get_property ( ofdev - > node , " compatible " , & cplen ) ;
2007-02-12 23:13:25 +01:00
if ( ! compat )
return csize ;
/* Find true end (we tolerate multiple \0 at the end */
for ( i = ( cplen - 1 ) ; i > = 0 & & ! compat [ i ] ; i - - )
cplen - - ;
if ( ! cplen )
return csize ;
cplen + + ;
/* Check space (need cplen+1 chars including final \0) */
tsize = csize + cplen ;
repend = tsize ;
if ( csize > = len ) /* @ the limit, all is already filled */
return tsize ;
if ( tsize > = len ) { /* limit compat list */
cplen = len - csize - 1 ;
repend = len ;
}
/* Copy and do char replacement */
memcpy ( & str [ csize + 1 ] , compat , cplen ) ;
for ( i = csize ; i < repend ; i + + ) {
char c = str [ i ] ;
if ( c = = ' \0 ' )
str [ i ] = ' C ' ;
else if ( c = = ' ' )
str [ i ] = ' _ ' ;
}
return tsize ;
}
2007-08-14 15:15:12 +02:00
int of_device_uevent ( struct device * dev , struct kobj_uevent_env * env )
2007-02-12 23:13:25 +01:00
{
struct of_device * ofdev ;
const char * compat ;
2007-08-14 15:15:12 +02:00
int seen = 0 , cplen , sl ;
2007-02-12 23:13:25 +01:00
if ( ! dev )
return - ENODEV ;
ofdev = to_of_device ( dev ) ;
2007-08-14 15:15:12 +02:00
if ( add_uevent_var ( env , " OF_NAME=%s " , ofdev - > node - > name ) )
2007-02-12 23:13:25 +01:00
return - ENOMEM ;
2007-08-14 15:15:12 +02:00
if ( add_uevent_var ( env , " OF_TYPE=%s " , ofdev - > node - > type ) )
2007-02-12 23:13:25 +01:00
return - ENOMEM ;
/* Since the compatible field can contain pretty much anything
* it ' s not really legal to split it out with commas . We split it
* up using a number of environment variables instead . */
2007-04-13 17:14:22 +10:00
compat = of_get_property ( ofdev - > node , " compatible " , & cplen ) ;
2007-02-12 23:13:25 +01:00
while ( compat & & * compat & & cplen > 0 ) {
2007-08-14 15:15:12 +02:00
if ( add_uevent_var ( env , " OF_COMPATIBLE_%d=%s " , seen , compat ) )
2007-02-12 23:13:25 +01:00
return - ENOMEM ;
sl = strlen ( compat ) + 1 ;
compat + = sl ;
cplen - = sl ;
seen + + ;
}
2007-08-14 15:15:12 +02:00
if ( add_uevent_var ( env , " OF_COMPATIBLE_N=%d " , seen ) )
2007-02-12 23:13:25 +01:00
return - ENOMEM ;
/* modalias is trickier, we add it in 2 steps */
2007-08-14 15:15:12 +02:00
if ( add_uevent_var ( env , " MODALIAS= " ) )
2007-02-12 23:13:25 +01:00
return - ENOMEM ;
2007-08-14 15:15:12 +02:00
sl = of_device_get_modalias ( ofdev , & env - > buf [ env - > buflen - 1 ] ,
sizeof ( env - > buf ) - env - > buflen ) ;
if ( sl > = ( sizeof ( env - > buf ) - env - > buflen ) )
2007-02-12 23:13:25 +01:00
return - ENOMEM ;
2007-08-14 15:15:12 +02:00
env - > buflen + = sl ;
2007-02-12 23:13:25 +01:00
return 0 ;
}
EXPORT_SYMBOL ( of_device_uevent ) ;
2007-05-07 01:38:46 +10:00
EXPORT_SYMBOL ( of_device_get_modalias ) ;