| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The GSM code is from TOAST.  Copyright information for that package is available | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * in the GSM directory. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 1999 - 2005, Digium, Inc. | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * \brief Translate between signed linear and Global System for Mobile Communications (GSM) | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-11-06 15:09:47 +00:00
										 |  |  |  * \ingroup codecs | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							| 
									
										
										
										
											2006-07-05 20:12:29 +00:00
										 |  |  | 	<depend>gsm</depend> | 
					
						
							| 
									
										
										
										
											2011-07-14 20:28:54 +00:00
										 |  |  | 	<support_level>core</support_level> | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/translate.h"
 | 
					
						
							|  |  |  | #include "asterisk/config.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							| 
									
										
										
										
											2006-01-21 08:45:39 +00:00
										 |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-30 23:27:16 +00:00
										 |  |  | #ifdef HAVE_GSM_HEADER
 | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  | #include "gsm.h"
 | 
					
						
							| 
									
										
										
										
											2007-01-30 23:27:16 +00:00
										 |  |  | #elif defined(HAVE_GSM_GSM_HEADER)
 | 
					
						
							|  |  |  | #include <gsm/gsm.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-12-20 08:16:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-07 06:00:13 +00:00
										 |  |  | #include "../formats/msgsm.h"
 | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | #define BUFFER_SAMPLES	8000
 | 
					
						
							|  |  |  | #define GSM_SAMPLES	160
 | 
					
						
							|  |  |  | #define	GSM_FRAME_LEN	33
 | 
					
						
							|  |  |  | #define	MSGSM_FRAME_LEN	65
 | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-17 21:35:23 +00:00
										 |  |  | /* Sample frame data */ | 
					
						
							|  |  |  | #include "asterisk/slin.h"
 | 
					
						
							|  |  |  | #include "ex_gsm.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | struct gsm_translator_pvt {	/* both gsm2lin and lin2gsm */ | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	gsm gsm; | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	int16_t buf[BUFFER_SAMPLES];	/* lin2gsm, temporary storage */ | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-24 19:43:31 +00:00
										 |  |  | static int gsm_new(struct ast_trans_pvt *pvt) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct gsm_translator_pvt *tmp = pvt->pvt; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-06-24 19:43:31 +00:00
										 |  |  | 	return (tmp->gsm = gsm_create()) ? 0 : -1; | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief decode and store in outbuf. */ | 
					
						
							|  |  |  | static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct gsm_translator_pvt *tmp = pvt->pvt; | 
					
						
							| 
									
										
										
										
											2001-03-22 04:20:13 +00:00
										 |  |  | 	int x; | 
					
						
							| 
									
										
										
										
											2008-06-26 17:06:17 +00:00
										 |  |  | 	int16_t *dst = pvt->outbuf.i16; | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	/* guess format from frame len. 65 for MSGSM, 33 for regular GSM */ | 
					
						
							|  |  |  | 	int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ? | 
					
						
							|  |  |  | 		MSGSM_FRAME_LEN : GSM_FRAME_LEN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (x=0; x < f->datalen; x += flen) { | 
					
						
							|  |  |  | 		unsigned char data[2 * GSM_FRAME_LEN]; | 
					
						
							| 
									
										
										
										
											2006-07-07 16:03:56 +00:00
										 |  |  | 		unsigned char *src; | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 		int len; | 
					
						
							|  |  |  | 		if (flen == MSGSM_FRAME_LEN) { | 
					
						
							|  |  |  | 			len = 2*GSM_SAMPLES; | 
					
						
							|  |  |  | 			src = data; | 
					
						
							| 
									
										
										
										
											2003-03-07 06:00:13 +00:00
										 |  |  | 			/* Translate MSGSM format to Real GSM format before feeding in */ | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 			/* XXX what's the point here! we should just work
 | 
					
						
							|  |  |  | 			 * on the full format. | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2008-05-22 16:29:54 +00:00
										 |  |  | 			conv65(f->data.ptr + x, data); | 
					
						
							| 
									
										
										
										
											2001-03-22 04:20:13 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 			len = GSM_SAMPLES; | 
					
						
							| 
									
										
										
										
											2008-05-22 16:29:54 +00:00
										 |  |  | 			src = f->data.ptr + x; | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		/* XXX maybe we don't need to check */ | 
					
						
							|  |  |  | 		if (pvt->samples + len > BUFFER_SAMPLES) {	 | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Out of buffer space\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Invalid GSM data (1)\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pvt->samples += GSM_SAMPLES; | 
					
						
							|  |  |  | 		pvt->datalen += 2 * GSM_SAMPLES; | 
					
						
							|  |  |  | 		if (flen == MSGSM_FRAME_LEN) { | 
					
						
							|  |  |  | 			if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) { | 
					
						
							|  |  |  | 				ast_log(LOG_WARNING, "Invalid GSM data (2)\n"); | 
					
						
							| 
									
										
										
										
											2003-03-07 06:00:13 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 			pvt->samples += GSM_SAMPLES; | 
					
						
							|  |  |  | 			pvt->datalen += 2 * GSM_SAMPLES; | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief store samples into working buffer for later decode */ | 
					
						
							|  |  |  | static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct gsm_translator_pvt *tmp = pvt->pvt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	/* XXX We should look at how old the rest of our stream is, and if it
 | 
					
						
							|  |  |  | 	   is too old, then we should overwrite it entirely, otherwise we can | 
					
						
							|  |  |  | 	   get artifacts of earlier talk that do not belong */ | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	if (pvt->samples + f->samples > BUFFER_SAMPLES) { | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Out of buffer space\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-22 16:29:54 +00:00
										 |  |  | 	memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen); | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	pvt->samples += f->samples; | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief encode and produce a frame */ | 
					
						
							|  |  |  | static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct gsm_translator_pvt *tmp = pvt->pvt; | 
					
						
							|  |  |  | 	int datalen = 0; | 
					
						
							|  |  |  | 	int samples = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	/* We can't work on anything less than a frame in size */ | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	if (pvt->samples < GSM_SAMPLES) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	while (pvt->samples >= GSM_SAMPLES) { | 
					
						
							| 
									
										
										
										
											2001-03-22 04:20:13 +00:00
										 |  |  | 		/* Encode a frame of data */ | 
					
						
							| 
									
										
										
										
											2008-06-26 17:06:17 +00:00
										 |  |  | 		gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf.c + datalen); | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 		datalen += GSM_FRAME_LEN; | 
					
						
							|  |  |  | 		samples += GSM_SAMPLES; | 
					
						
							|  |  |  | 		pvt->samples -= GSM_SAMPLES; | 
					
						
							| 
									
										
										
										
											2001-03-22 04:20:13 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-08 21:33:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Move the data at the end of the buffer to the front */ | 
					
						
							|  |  |  | 	if (pvt->samples) | 
					
						
							|  |  |  | 		memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	return ast_trans_frameout(pvt, datalen, samples); | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | static void gsm_destroy_stuff(struct ast_trans_pvt *pvt) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct gsm_translator_pvt *tmp = pvt->pvt; | 
					
						
							|  |  |  | 	if (tmp->gsm) | 
					
						
							|  |  |  | 		gsm_destroy(tmp->gsm); | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | static struct ast_translator gsmtolin = { | 
					
						
							|  |  |  | 	.name = "gsmtolin",  | 
					
						
							|  |  |  | 	.newpvt = gsm_new, | 
					
						
							|  |  |  | 	.framein = gsmtolin_framein, | 
					
						
							|  |  |  | 	.destroy = gsm_destroy_stuff, | 
					
						
							| 
									
										
										
										
											2008-10-17 21:35:23 +00:00
										 |  |  | 	.sample = gsm_sample, | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	.buffer_samples = BUFFER_SAMPLES, | 
					
						
							|  |  |  | 	.buf_size = BUFFER_SAMPLES * 2, | 
					
						
							|  |  |  | 	.desc_size = sizeof (struct gsm_translator_pvt ), | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | static struct ast_translator lintogsm = { | 
					
						
							|  |  |  | 	.name = "lintogsm",  | 
					
						
							|  |  |  | 	.newpvt = gsm_new, | 
					
						
							|  |  |  | 	.framein = lintogsm_framein, | 
					
						
							|  |  |  | 	.frameout = lintogsm_frameout, | 
					
						
							|  |  |  | 	.destroy = gsm_destroy_stuff, | 
					
						
							| 
									
										
										
										
											2008-10-17 21:35:23 +00:00
										 |  |  | 	.sample = slin8_sample, | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	.desc_size = sizeof (struct gsm_translator_pvt ), | 
					
						
							|  |  |  | 	.buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief standard module glue */ | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int reload(void) | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-31 19:24:29 +00:00
										 |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	res = ast_unregister_translator(&lintogsm); | 
					
						
							|  |  |  | 	if (!res) | 
					
						
							|  |  |  | 		res = ast_unregister_translator(&gsmtolin); | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-03 16:22:10 +00:00
										 |  |  | 	ast_format_set(&gsmtolin.src_format, AST_FORMAT_GSM, 0); | 
					
						
							|  |  |  | 	ast_format_set(&gsmtolin.dst_format, AST_FORMAT_SLINEAR, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_format_set(&lintogsm.src_format, AST_FORMAT_SLINEAR, 0); | 
					
						
							|  |  |  | 	ast_format_set(&lintogsm.dst_format, AST_FORMAT_GSM, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 	res = ast_register_translator(&gsmtolin); | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	if (!res)  | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 		res=ast_register_translator(&lintogsm); | 
					
						
							| 
									
										
										
										
											1999-11-15 06:08:50 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		ast_unregister_translator(&gsmtolin); | 
					
						
							| 
									
										
										
										
											2007-10-31 19:24:29 +00:00
										 |  |  | 	if (res)  | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_FAILURE; | 
					
						
							|  |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2001-03-22 04:20:13 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-04-14 14:08:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GSM Coder/Decoder", | 
					
						
							|  |  |  | 		.load = load_module, | 
					
						
							|  |  |  | 		.unload = unload_module, | 
					
						
							|  |  |  | 		.reload = reload, | 
					
						
							|  |  |  | 	       ); |