diff options
| -rw-r--r-- | daemon/main.c | 2 | ||||
| -rw-r--r-- | hcid/hcid.conf.5 | 6 | ||||
| -rw-r--r-- | hcid/hcid.h | 3 | ||||
| -rw-r--r-- | hcid/kword.c | 1 | ||||
| -rw-r--r-- | hcid/lexer.l | 9 | ||||
| -rw-r--r-- | hcid/main.c | 2 | ||||
| -rw-r--r-- | hcid/parser.y | 14 | ||||
| -rw-r--r-- | sdpd/main.c | 2 | ||||
| -rw-r--r-- | sdpd/sdpd.h | 4 | ||||
| -rw-r--r-- | sdpd/server.c | 18 | ||||
| -rw-r--r-- | sdpd/service.c | 63 | 
11 files changed, 112 insertions, 12 deletions
| diff --git a/daemon/main.c b/daemon/main.c index 1653ba75..fe0fa404 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -212,7 +212,7 @@ int main(int argc, char *argv[])  		exit(1);  	} -	if (start_sdp_server(0, SDP_SERVER_COMPAT) < 0) { +	if (start_sdp_server(0, NULL, SDP_SERVER_COMPAT) < 0) {  		cleanup_dbus();  		g_main_loop_unref(main_loop);  		exit(1); diff --git a/hcid/hcid.conf.5 b/hcid/hcid.conf.5 index 1dad854d..cb5bcfa9 100644 --- a/hcid/hcid.conf.5 +++ b/hcid/hcid.conf.5 @@ -53,6 +53,12 @@ SetMode("off"). \fIdevdown\fP sets the adapter into down state (same what  \fIhciconfig hci0 down\fP does).  .TP +\fBdeviceid\fP	<vendor>:<product>:<version> + +This option allows to specify the vendor and product information of the +Bluetooth device ID service record. + +.TP  \fBpasskey\fP "\fIpin\fP"  The default PIN for incoming connections if \fBsecurity\fP has been diff --git a/hcid/hcid.h b/hcid/hcid.h index 8983a899..86b21639 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -76,7 +76,7 @@ struct device_opts {  	uint16_t link_mode;  	uint16_t link_policy;  	uint8_t  scan; -	int      discovto; +	uint32_t discovto;  };  extern struct device_opts default_device; @@ -94,6 +94,7 @@ struct hcid_opts {  	int     security;  	int     pairing;  	int	offmode; +        char    deviceid[15];  	char   *config_file; diff --git a/hcid/kword.c b/hcid/kword.c index 2a51a0b3..7d2c694c 100644 --- a/hcid/kword.c +++ b/hcid/kword.c @@ -49,6 +49,7 @@ struct kword cfg_keyword[] = {  	{ "security",		K_SECURITY	},  	{ "pairing",		K_PAIRING	},  	{ "offmode",		K_OFFMODE	}, +	{ "deviceid",		K_DEVICEID	},  	{ "pkt_type",		K_PTYPE		},  	{ "lm", 		K_LM		},  	{ "lp", 		K_LP		}, diff --git a/hcid/lexer.l b/hcid/lexer.l index a194f708..f4559494 100644 --- a/hcid/lexer.l +++ b/hcid/lexer.l @@ -63,7 +63,9 @@ path		(\/{fname})+  string		\".*\"  hci		hci[0-9]+  hextuple	[0-9a-zA-Z][0-9a-zA-Z] +hexquad		{hextuple}{hextuple}  bdaddr		{hextuple}:{hextuple}:{hextuple}:{hextuple}:{hextuple}:{hextuple} +id		{hexquad}:{hexquad}  %x OPTION PARAM @@ -117,7 +119,7 @@ bdaddr		{hextuple}:{hextuple}:{hextuple}:{hextuple}:{hextuple}:{hextuple}  }  {string} { -	if(yyleng > sizeof(str_buf) - 1){ +	if (yyleng > sizeof(str_buf) - 1) {  		yyerror("string too long");  		return 0;  	} @@ -139,6 +141,11 @@ bdaddr		{hextuple}:{hextuple}:{hextuple}:{hextuple}:{hextuple}:{hextuple}  	return PATH;  } +{id} { +	yylval.str = yytext; +	return ID; +} +  . {  	return *yytext;  } diff --git a/hcid/main.c b/hcid/main.c index 641cc801..943d6cf4 100644 --- a/hcid/main.c +++ b/hcid/main.c @@ -783,7 +783,7 @@ int main(int argc, char *argv[])  	if (sdp) {  		set_sdp_server_enable(); -		start_sdp_server(0, SDP_SERVER_COMPAT); +		start_sdp_server(0, hcid.deviceid, SDP_SERVER_COMPAT);  	}  	notify_init(); diff --git a/hcid/parser.y b/hcid/parser.y index aa16a5c7..4641a0ac 100644 --- a/hcid/parser.y +++ b/hcid/parser.y @@ -62,16 +62,16 @@ void yylex_destroy(void);  }  %token K_OPTIONS K_DEVICE -%token K_AUTOINIT K_SECURITY K_PAIRING K_OFFMODE +%token K_AUTOINIT K_SECURITY K_PAIRING K_OFFMODE K_DEVICEID  %token K_PTYPE K_NAME K_CLASS K_VOICE K_PAGETO K_LM K_LP K_ISCAN K_PSCAN K_DISCOVTO  %token K_PASSKEY  %token K_YES K_NO -%token <str> WORD PATH STRING LIST HCI BDADDR +%token <str> WORD PATH STRING LIST HCI BDADDR ID  %token <num> NUM  %type  <num> bool pkt_type link_mode link_policy sec_mode pair_mode off_mode -%type  <str> dev_name hci bdaddr +%type  <str> dev_name dev_id hci bdaddr  %%  config: statement | config statement; @@ -122,6 +122,10 @@ hcid_opt:  				hcid.offmode = $2;  			} +  | K_DEVICEID dev_id	{ +				strncpy((char *) hcid.deviceid, $2, 15); +			} +    | K_PASSKEY STRING	{    				strncpy((char *) hcid.pin_code, $2, 16);  				hcid.pin_len = strlen($2); @@ -172,6 +176,10 @@ off_mode:  		}    ; +dev_id: +  ID		{ +		} +  ;  device_options: '{' device_opts '}';  device_opts: | device_opt ';' | error ';' | device_opts device_opt ';'; diff --git a/sdpd/main.c b/sdpd/main.c index 4027ae96..856c6cb3 100644 --- a/sdpd/main.c +++ b/sdpd/main.c @@ -139,7 +139,7 @@ int main(int argc, char *argv[])  	event_loop = g_main_loop_new(NULL, FALSE); -	if (start_sdp_server(mtu, flags) < 0) { +	if (start_sdp_server(mtu, NULL, flags) < 0) {  		g_main_loop_unref(event_loop);  		exit(1);  	} diff --git a/sdpd/sdpd.h b/sdpd/sdpd.h index 8ec47b1a..13aa2c74 100644 --- a/sdpd/sdpd.h +++ b/sdpd/sdpd.h @@ -46,6 +46,8 @@ int service_remove_req(sdp_req_t *req, sdp_buf_t *rsp);  void register_public_browse_group(int public);  void register_server_service(int public); +void register_device_id(const uint16_t vendor, const uint16_t product, +						const uint16_t version);  typedef struct {  	uint32_t timestamp; @@ -80,7 +82,7 @@ uint32_t sdp_get_time();  #define SDP_SERVER_MASTER (1 << 1)  #define SDP_SERVER_PUBLIC (1 << 2) -int start_sdp_server(uint16_t mtu, uint32_t flags); +int start_sdp_server(uint16_t mtu, const char *did, uint32_t flags);  void stop_sdp_server(void);  int add_record_to_server(sdp_record_t *rec); diff --git a/sdpd/server.c b/sdpd/server.c index 2abcc6bc..fab17f00 100644 --- a/sdpd/server.c +++ b/sdpd/server.c @@ -31,6 +31,7 @@  #include <stdio.h>  #include <errno.h>  #include <unistd.h> +#include <stdlib.h>  #include <sys/stat.h>  #include <sys/socket.h> @@ -215,7 +216,7 @@ static gboolean io_accept_event(GIOChannel *chan, GIOCondition cond, gpointer da  	return TRUE;  } -int start_sdp_server(uint16_t mtu, uint32_t flags) +int start_sdp_server(uint16_t mtu, const char *did, uint32_t flags)  {  	int compat = flags & SDP_SERVER_COMPAT;  	int master = flags & SDP_SERVER_MASTER; @@ -228,6 +229,21 @@ int start_sdp_server(uint16_t mtu, uint32_t flags)  		return -1;  	} +	if (did && strlen(did) > 0) { +		const char *ptr = did; +		uint16_t vid = 0x0000, pid = 0x0000, ver = 0x0000; + +		vid = (uint16_t) strtol(ptr, NULL, 16); +		ptr = strchr(ptr, ':'); +		if (ptr) { +			pid = (uint16_t) strtol(ptr + 1, NULL, 16); +			ptr = strchr(ptr + 1, ':'); +			if (ptr) +				ver = (uint16_t) strtol(ptr + 1, NULL, 16); +			register_device_id(vid, pid, ver); +		} +	} +  	l2cap_io = g_io_channel_unix_new(l2cap_sock);  	g_io_channel_set_close_on_unref(l2cap_io, TRUE); diff --git a/sdpd/service.c b/sdpd/service.c index 69c5242b..8c8c3a73 100644 --- a/sdpd/service.c +++ b/sdpd/service.c @@ -102,7 +102,8 @@ void register_public_browse_group(int public)  	sdp_attr_add(browse, SDP_ATTR_RECORD_HANDLE, sdpdata);  	add_lang_attr(browse); -	sdp_set_info_attr(browse, "Public Browse Group Root", "BlueZ", "Root of public browse hierarchy"); +	sdp_set_info_attr(browse, "Public Browse Group Root", "BlueZ", +					"Root of public browse hierarchy");  	sdp_uuid16_create(&bgscid, BROWSE_GRP_DESC_SVCLASS_ID);  	browselist = sdp_list_append(0, &bgscid); @@ -140,7 +141,8 @@ void register_server_service(int public)  	server->handle = SDP_SERVER_RECORD_HANDLE;  	sdp_record_add(BDADDR_ANY, server); -	sdp_attr_add(server, SDP_ATTR_RECORD_HANDLE, sdp_data_alloc(SDP_UINT32, &server->handle)); +	sdp_attr_add(server, SDP_ATTR_RECORD_HANDLE, +				sdp_data_alloc(SDP_UINT32, &server->handle));  	/*  	 * Add all attributes to service record. (No need to commit since we  @@ -207,6 +209,63 @@ void register_server_service(int public)  	update_db_timestamp();  } +void register_device_id(const uint16_t vendor, const uint16_t product, +						const uint16_t version) +{ +	const uint16_t spec = 0x0102, source = 0x0002; +	const uint8_t primary = 1; +	sdp_list_t *class_list, *group_list, *profile_list; +	uuid_t class_uuid, group_uuid; +	sdp_data_t *sdp_data, *primary_data, *source_data; +	sdp_data_t *spec_data, *vendor_data, *product_data, *version_data; +	sdp_profile_desc_t profile; +	sdp_record_t *record = sdp_record_alloc(); + +	info("Adding device id record for %04x:%04x", vendor, product); + +	record->handle = sdp_next_handle(); + +	sdp_record_add(BDADDR_ANY, record); +	sdp_data = sdp_data_alloc(SDP_UINT32, &record->handle); +	sdp_attr_add(record, SDP_ATTR_RECORD_HANDLE, sdp_data); + +	sdp_uuid16_create(&class_uuid, PNP_INFO_SVCLASS_ID); +	class_list = sdp_list_append(0, &class_uuid); +	sdp_set_service_classes(record, class_list); +	sdp_list_free(class_list, NULL); + +	sdp_uuid16_create(&group_uuid, PUBLIC_BROWSE_GROUP); +	group_list = sdp_list_append(NULL, &group_uuid); +	sdp_set_browse_groups(record, group_list); +	sdp_list_free(group_list, NULL); + +	sdp_uuid16_create(&profile.uuid, PNP_INFO_PROFILE_ID); +	profile.version = spec; +	profile_list = sdp_list_append(NULL, &profile); +	sdp_set_profile_descs(record, profile_list); +	sdp_list_free(profile_list, NULL); + +	spec_data = sdp_data_alloc(SDP_UINT16, &spec); +	sdp_attr_add(record, 0x0200, spec_data); + +	vendor_data = sdp_data_alloc(SDP_UINT16, &vendor); +	sdp_attr_add(record, 0x0201, vendor_data); + +	product_data = sdp_data_alloc(SDP_UINT16, &product); +	sdp_attr_add(record, 0x0202, product_data); + +	version_data = sdp_data_alloc(SDP_UINT16, &version); +	sdp_attr_add(record, 0x0203, version_data); + +	primary_data = sdp_data_alloc(SDP_BOOL, &primary); +	sdp_attr_add(record, 0x0204, primary_data); + +	source_data = sdp_data_alloc(SDP_UINT16, &source); +	sdp_attr_add(record, 0x0205, source_data); + +	update_db_timestamp(); +} +  int add_record_to_server(sdp_record_t *rec)  {  	sdp_data_t *data; | 
