| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * | 
 | 3 |   Copyright (c) Eicon Networks, 2002. | 
 | 4 |  * | 
 | 5 |   This source file is supplied for the use with | 
 | 6 |   Eicon Networks range of DIVA Server Adapters. | 
 | 7 |  * | 
 | 8 |   Eicon File Revision :    2.1 | 
 | 9 |  * | 
 | 10 |   This program is free software; you can redistribute it and/or modify | 
 | 11 |   it under the terms of the GNU General Public License as published by | 
 | 12 |   the Free Software Foundation; either version 2, or (at your option) | 
 | 13 |   any later version. | 
 | 14 |  * | 
 | 15 |   This program is distributed in the hope that it will be useful, | 
 | 16 |   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY | 
 | 17 |   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
 | 18 |   See the GNU General Public License for more details. | 
 | 19 |  * | 
 | 20 |   You should have received a copy of the GNU General Public License | 
 | 21 |   along with this program; if not, write to the Free Software | 
 | 22 |   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
 | 23 |  * | 
 | 24 |  */ | 
 | 25 |  | 
 | 26 |  | 
 | 27 |  | 
 | 28 |  | 
 | 29 |  | 
 | 30 | #include "platform.h" | 
 | 31 | #include "di_defs.h" | 
 | 32 | #include "pc.h" | 
 | 33 | #include "capi20.h" | 
 | 34 | #include "divacapi.h" | 
 | 35 | #include "mdm_msg.h" | 
 | 36 | #include "divasync.h" | 
 | 37 |  | 
 | 38 |  | 
 | 39 |  | 
 | 40 | #define FILE_ "MESSAGE.C" | 
 | 41 | #define dprintf | 
 | 42 |  | 
 | 43 |  | 
 | 44 |  | 
 | 45 |  | 
 | 46 |  | 
 | 47 |  | 
 | 48 |  | 
 | 49 |  | 
 | 50 |  | 
 | 51 | /*------------------------------------------------------------------*/ | 
 | 52 | /* This is options supported for all adapters that are server by    */ | 
 | 53 | /* XDI driver. Allo it is not necessary to ask it from every adapter*/ | 
 | 54 | /* and it is not necessary to save it separate for every adapter    */ | 
 | 55 | /* Macrose defined here have only local meaning                     */ | 
 | 56 | /*------------------------------------------------------------------*/ | 
 | 57 | static dword diva_xdi_extended_features = 0; | 
 | 58 |  | 
 | 59 | #define DIVA_CAPI_USE_CMA                 0x00000001 | 
 | 60 | #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002 | 
 | 61 | #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004 | 
 | 62 | #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008 | 
 | 63 |  | 
 | 64 | /* | 
 | 65 |   CAPI can request to process all return codes self only if: | 
 | 66 |   protocol code supports this && xdi supports this | 
 | 67 |  */ | 
 | 68 | #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL)) | 
 | 69 |  | 
 | 70 | /*------------------------------------------------------------------*/ | 
 | 71 | /* local function prototypes                                        */ | 
 | 72 | /*------------------------------------------------------------------*/ | 
 | 73 |  | 
 | 74 | static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci); | 
 | 75 | static void set_group_ind_mask (PLCI   *plci); | 
 | 76 | static void clear_group_ind_mask_bit (PLCI   *plci, word b); | 
 | 77 | static byte test_group_ind_mask_bit (PLCI   *plci, word b); | 
 | 78 | void AutomaticLaw(DIVA_CAPI_ADAPTER   *); | 
 | 79 | word CapiRelease(word); | 
 | 80 | word CapiRegister(word); | 
 | 81 | word api_put(APPL   *, CAPI_MSG   *); | 
 | 82 | static word api_parse(byte   *, word, byte *, API_PARSE *); | 
 | 83 | static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out); | 
 | 84 | static void api_load_msg(API_SAVE   *in, API_PARSE   *out); | 
 | 85 |  | 
 | 86 | word api_remove_start(void); | 
 | 87 | void api_remove_complete(void); | 
 | 88 |  | 
 | 89 | static void plci_remove(PLCI   *); | 
 | 90 | static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a); | 
 | 91 | static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *); | 
 | 92 |  | 
 | 93 | void   callback(ENTITY   *); | 
 | 94 |  | 
 | 95 | static void control_rc(PLCI   *, byte, byte, byte, byte, byte); | 
 | 96 | static void data_rc(PLCI   *, byte); | 
 | 97 | static void data_ack(PLCI   *, byte); | 
 | 98 | static void sig_ind(PLCI   *); | 
 | 99 | static void SendInfo(PLCI   *, dword, byte   * *, byte); | 
 | 100 | static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte); | 
 | 101 | static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms); | 
 | 102 |  | 
 | 103 | static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms); | 
 | 104 |  | 
 | 105 | static void nl_ind(PLCI   *); | 
 | 106 |  | 
 | 107 | static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 108 | static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 109 | static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 110 | static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 111 | static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 112 | static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 113 | static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 114 | static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 115 | static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 116 | static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 117 | static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 118 | static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 119 | static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 120 | static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 121 | static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 122 | static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 123 | static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 124 | static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 125 | static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 126 | static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 127 | static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 128 | static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 129 | static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 130 | static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 131 |  | 
 | 132 | static word get_plci(DIVA_CAPI_ADAPTER   *); | 
 | 133 | static void add_p(PLCI   *, byte, byte   *); | 
 | 134 | static void add_s(PLCI   * plci, byte code, API_PARSE * p); | 
 | 135 | static void add_ss(PLCI   * plci, byte code, API_PARSE * p); | 
 | 136 | static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length); | 
 | 137 | static void add_d(PLCI   *, word, byte   *); | 
 | 138 | static void add_ai(PLCI   *, API_PARSE *); | 
 | 139 | static word add_b1(PLCI   *, API_PARSE *, word, word); | 
 | 140 | static word add_b23(PLCI   *, API_PARSE *); | 
 | 141 | static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms); | 
 | 142 | static void sig_req(PLCI   *, byte, byte); | 
 | 143 | static void nl_req_ncci(PLCI   *, byte, byte); | 
 | 144 | static void send_req(PLCI   *); | 
 | 145 | static void send_data(PLCI   *); | 
 | 146 | static word plci_remove_check(PLCI   *); | 
 | 147 | static void listen_check(DIVA_CAPI_ADAPTER   *); | 
 | 148 | static byte AddInfo(byte   **, byte   **, byte   *, byte *); | 
 | 149 | static byte getChannel(API_PARSE *); | 
 | 150 | static void IndParse(PLCI   *, word *, byte   **, byte); | 
 | 151 | static byte ie_compare(byte   *, byte *); | 
 | 152 | static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *); | 
 | 153 | static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word); | 
 | 154 |  | 
 | 155 | /* | 
 | 156 |   XON protocol helpers | 
 | 157 |   */ | 
 | 158 | static void channel_flow_control_remove (PLCI   * plci); | 
 | 159 | static void channel_x_off (PLCI   * plci, byte ch, byte flag); | 
 | 160 | static void channel_x_on (PLCI   * plci, byte ch); | 
 | 161 | static void channel_request_xon (PLCI   * plci, byte ch); | 
 | 162 | static void channel_xmit_xon (PLCI   * plci); | 
 | 163 | static int channel_can_xon (PLCI   * plci, byte ch); | 
 | 164 | static void channel_xmit_extended_xon (PLCI   * plci); | 
 | 165 |  | 
 | 166 | static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse); | 
 | 167 | static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte); | 
 | 168 | static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *); | 
 | 169 | static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * ); | 
 | 170 | static void VoiceChannelOff(PLCI   *plci); | 
 | 171 | static void adv_voice_write_coefs (PLCI   *plci, word write_command); | 
 | 172 | static void adv_voice_clear_config (PLCI   *plci); | 
 | 173 |  | 
 | 174 | static word get_b1_facilities (PLCI   * plci, byte b1_resource); | 
 | 175 | static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities); | 
 | 176 | static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities); | 
 | 177 | static word adjust_b_process (dword Id, PLCI   *plci, byte Rc); | 
 | 178 | static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command); | 
 | 179 | static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc); | 
 | 180 | static void reset_b3_command (dword Id, PLCI   *plci, byte Rc); | 
 | 181 | static void select_b_command (dword Id, PLCI   *plci, byte Rc); | 
 | 182 | static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc); | 
 | 183 | static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc); | 
 | 184 | static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc); | 
 | 185 | static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc); | 
 | 186 | static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc); | 
 | 187 | static void hold_save_command (dword Id, PLCI   *plci, byte Rc); | 
 | 188 | static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc); | 
 | 189 | static void init_b1_config (PLCI   *plci); | 
 | 190 | static void clear_b1_config (PLCI   *plci); | 
 | 191 |  | 
 | 192 | static void dtmf_command (dword Id, PLCI   *plci, byte Rc); | 
 | 193 | static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg); | 
 | 194 | static void dtmf_confirmation (dword Id, PLCI   *plci); | 
 | 195 | static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length); | 
 | 196 | static void dtmf_parameter_write (PLCI   *plci); | 
 | 197 |  | 
 | 198 |  | 
 | 199 | static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id); | 
 | 200 | static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi); | 
 | 201 | static void mixer_clear_config (PLCI   *plci); | 
 | 202 | static void mixer_notify_update (PLCI   *plci, byte others); | 
 | 203 | static void mixer_command (dword Id, PLCI   *plci, byte Rc); | 
 | 204 | static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg); | 
 | 205 | static void mixer_indication_coefs_set (dword Id, PLCI   *plci); | 
 | 206 | static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length); | 
 | 207 | static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length); | 
 | 208 | static void mixer_remove (PLCI   *plci); | 
 | 209 |  | 
 | 210 |  | 
 | 211 | static void ec_command (dword Id, PLCI   *plci, byte Rc); | 
 | 212 | static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg); | 
 | 213 | static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length); | 
 | 214 |  | 
 | 215 |  | 
 | 216 | static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc); | 
 | 217 | static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc); | 
 | 218 |  | 
 | 219 |  | 
 | 220 | static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic); | 
 | 221 | static void diva_free_dma_descriptor (PLCI   *plci, int nr); | 
 | 222 |  | 
 | 223 | /*------------------------------------------------------------------*/ | 
 | 224 | /* external function prototypes                                     */ | 
 | 225 | /*------------------------------------------------------------------*/ | 
 | 226 |  | 
 | 227 | extern byte MapController (byte); | 
 | 228 | extern byte UnMapController (byte); | 
 | 229 | #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id))) | 
 | 230 | #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id))) | 
 | 231 |  | 
 | 232 | void   sendf(APPL   *, word, dword, word, byte *, ...); | 
 | 233 | void   * TransmitBufferSet(APPL   * appl, dword ref); | 
 | 234 | void   * TransmitBufferGet(APPL   * appl, void   * p); | 
 | 235 | void TransmitBufferFree(APPL   * appl, void   * p); | 
 | 236 | void   * ReceiveBufferGet(APPL   * appl, int Num); | 
 | 237 |  | 
 | 238 | int fax_head_line_time (char *buffer); | 
 | 239 |  | 
 | 240 |  | 
 | 241 | /*------------------------------------------------------------------*/ | 
 | 242 | /* Global data definitions                                          */ | 
 | 243 | /*------------------------------------------------------------------*/ | 
 | 244 | extern byte max_adapter; | 
 | 245 | extern byte max_appl; | 
 | 246 | extern DIVA_CAPI_ADAPTER   * adapter; | 
 | 247 | extern APPL   * application; | 
 | 248 |  | 
 | 249 |  | 
 | 250 |  | 
 | 251 |  | 
 | 252 |  | 
 | 253 |  | 
 | 254 |  | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 255 | static byte remove_started = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 256 | static PLCI dummy_plci; | 
 | 257 |  | 
 | 258 |  | 
 | 259 | static struct _ftable { | 
 | 260 |   word command; | 
 | 261 |   byte * format; | 
 | 262 |   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *); | 
 | 263 | } ftable[] = { | 
 | 264 |   {_DATA_B3_R,                          "dwww",         data_b3_req}, | 
 | 265 |   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res}, | 
 | 266 |   {_INFO_R,                             "ss",           info_req}, | 
 | 267 |   {_INFO_I|RESPONSE,                    "",             info_res}, | 
 | 268 |   {_CONNECT_R,                          "wsssssssss",   connect_req}, | 
 | 269 |   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res}, | 
 | 270 |   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res}, | 
 | 271 |   {_DISCONNECT_R,                       "s",            disconnect_req}, | 
 | 272 |   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res}, | 
 | 273 |   {_LISTEN_R,                           "dddss",        listen_req}, | 
 | 274 |   {_ALERT_R,                            "s",            alert_req}, | 
 | 275 |   {_FACILITY_R,                         "ws",           facility_req}, | 
 | 276 |   {_FACILITY_I|RESPONSE,                "ws",           facility_res}, | 
 | 277 |   {_CONNECT_B3_R,                       "s",            connect_b3_req}, | 
 | 278 |   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res}, | 
 | 279 |   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res}, | 
 | 280 |   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req}, | 
 | 281 |   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res}, | 
 | 282 |   {_RESET_B3_R,                         "s",            reset_b3_req}, | 
 | 283 |   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res}, | 
 | 284 |   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res}, | 
 | 285 |   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res}, | 
 | 286 |   {_SELECT_B_REQ,                       "s",            select_b_req}, | 
 | 287 |   {_MANUFACTURER_R,                     "dws",          manufacturer_req}, | 
 | 288 |   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res}, | 
 | 289 |   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res} | 
 | 290 | }; | 
 | 291 |  | 
 | 292 | static byte * cip_bc[29][2] = { | 
 | 293 |   { "",                     ""                     }, /* 0 */ | 
 | 294 |   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */ | 
 | 295 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */ | 
 | 296 |   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */ | 
 | 297 |   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */ | 
 | 298 |   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */ | 
 | 299 |   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */ | 
 | 300 |   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */ | 
 | 301 |   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */ | 
 | 302 |   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */ | 
 | 303 |   { "",                     ""                     }, /* 10 */ | 
 | 304 |   { "",                     ""                     }, /* 11 */ | 
 | 305 |   { "",                     ""                     }, /* 12 */ | 
 | 306 |   { "",                     ""                     }, /* 13 */ | 
 | 307 |   { "",                     ""                     }, /* 14 */ | 
 | 308 |   { "",                     ""                     }, /* 15 */ | 
 | 309 |  | 
 | 310 |   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */ | 
 | 311 |   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */ | 
 | 312 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */ | 
 | 313 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */ | 
 | 314 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */ | 
 | 315 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */ | 
 | 316 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */ | 
 | 317 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */ | 
 | 318 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */ | 
 | 319 |   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */ | 
 | 320 |   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */ | 
 | 321 |   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */ | 
 | 322 |   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */ | 
 | 323 | }; | 
 | 324 |  | 
 | 325 | static byte * cip_hlc[29] = { | 
 | 326 |   "",                           /* 0 */ | 
 | 327 |   "",                           /* 1 */ | 
 | 328 |   "",                           /* 2 */ | 
 | 329 |   "",                           /* 3 */ | 
 | 330 |   "",                           /* 4 */ | 
 | 331 |   "",                           /* 5 */ | 
 | 332 |   "",                           /* 6 */ | 
 | 333 |   "",                           /* 7 */ | 
 | 334 |   "",                           /* 8 */ | 
 | 335 |   "",                           /* 9 */ | 
 | 336 |   "",                           /* 10 */ | 
 | 337 |   "",                           /* 11 */ | 
 | 338 |   "",                           /* 12 */ | 
 | 339 |   "",                           /* 13 */ | 
 | 340 |   "",                           /* 14 */ | 
 | 341 |   "",                           /* 15 */ | 
 | 342 |  | 
 | 343 |   "\x02\x91\x81",               /* 16 */ | 
 | 344 |   "\x02\x91\x84",               /* 17 */ | 
 | 345 |   "\x02\x91\xa1",               /* 18 */ | 
 | 346 |   "\x02\x91\xa4",               /* 19 */ | 
 | 347 |   "\x02\x91\xa8",               /* 20 */ | 
 | 348 |   "\x02\x91\xb1",               /* 21 */ | 
 | 349 |   "\x02\x91\xb2",               /* 22 */ | 
 | 350 |   "\x02\x91\xb5",               /* 23 */ | 
 | 351 |   "\x02\x91\xb8",               /* 24 */ | 
 | 352 |   "\x02\x91\xc1",               /* 25 */ | 
 | 353 |   "\x02\x91\x81",               /* 26 */ | 
 | 354 |   "\x03\x91\xe0\x01",           /* 27 */ | 
 | 355 |   "\x03\x91\xe0\x02"            /* 28 */ | 
 | 356 | }; | 
 | 357 |  | 
 | 358 | /*------------------------------------------------------------------*/ | 
 | 359 |  | 
 | 360 | #define V120_HEADER_LENGTH 1 | 
 | 361 | #define V120_HEADER_EXTEND_BIT  0x80 | 
 | 362 | #define V120_HEADER_BREAK_BIT   0x40 | 
 | 363 | #define V120_HEADER_C1_BIT      0x04 | 
 | 364 | #define V120_HEADER_C2_BIT      0x08 | 
 | 365 | #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT) | 
 | 366 |  | 
 | 367 | static byte v120_default_header[] = | 
 | 368 | { | 
 | 369 |  | 
 | 370 |   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */ | 
 | 371 |  | 
 | 372 | }; | 
 | 373 |  | 
 | 374 | static byte v120_break_header[] = | 
 | 375 | { | 
 | 376 |  | 
 | 377 |   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */ | 
 | 378 |  | 
 | 379 | }; | 
 | 380 |  | 
 | 381 |  | 
 | 382 | /*------------------------------------------------------------------*/ | 
 | 383 | /* API_PUT function                                                 */ | 
 | 384 | /*------------------------------------------------------------------*/ | 
 | 385 |  | 
 | 386 | word api_put(APPL   * appl, CAPI_MSG   * msg) | 
 | 387 | { | 
 | 388 |   word i, j, k, l, n; | 
 | 389 |   word ret; | 
 | 390 |   byte c; | 
 | 391 |   byte controller; | 
 | 392 |   DIVA_CAPI_ADAPTER   * a; | 
 | 393 |   PLCI   * plci; | 
 | 394 |   NCCI   * ncci_ptr; | 
 | 395 |   word ncci; | 
 | 396 |   CAPI_MSG   *m; | 
 | 397 |     API_PARSE msg_parms[MAX_MSG_PARMS+1]; | 
 | 398 |  | 
 | 399 |   if (msg->header.length < sizeof (msg->header) || | 
 | 400 |       msg->header.length > MAX_MSG_SIZE) { | 
 | 401 |     dbug(1,dprintf("bad len")); | 
 | 402 |     return _BAD_MSG; | 
 | 403 |   } | 
 | 404 |  | 
 | 405 |   controller = (byte)((msg->header.controller &0x7f)-1); | 
 | 406 |  | 
 | 407 |   /* controller starts with 0 up to (max_adapter - 1) */ | 
 | 408 |   if ( controller >= max_adapter ) | 
 | 409 |   { | 
 | 410 |     dbug(1,dprintf("invalid ctrl")); | 
 | 411 |     return _BAD_MSG; | 
 | 412 |   } | 
 | 413 |    | 
 | 414 |   a = &adapter[controller]; | 
 | 415 |   plci = NULL; | 
 | 416 |   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled) | 
 | 417 |   { | 
 | 418 |     dbug(1,dprintf("plci=%x",msg->header.plci)); | 
 | 419 |     plci = &a->plci[msg->header.plci-1]; | 
 | 420 |     ncci = GET_WORD(&msg->header.ncci); | 
 | 421 |     if (plci->Id | 
 | 422 |      && (plci->appl | 
 | 423 |       || (plci->State == INC_CON_PENDING) | 
 | 424 |       || (plci->State == INC_CON_ALERT) | 
 | 425 |       || (msg->header.command == (_DISCONNECT_I|RESPONSE))) | 
 | 426 |      && ((ncci == 0) | 
 | 427 |       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE)) | 
 | 428 |       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id)))) | 
 | 429 |     { | 
 | 430 |       i = plci->msg_in_read_pos; | 
 | 431 |       j = plci->msg_in_write_pos; | 
 | 432 |       if (j >= i) | 
 | 433 |       { | 
 | 434 |         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE) | 
 | 435 |           i += MSG_IN_QUEUE_SIZE - j; | 
 | 436 |         else | 
 | 437 |           j = 0; | 
 | 438 |       } | 
 | 439 |       else | 
 | 440 |       { | 
 | 441 |  | 
 | 442 |         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc; | 
 | 443 |  | 
 | 444 |         if (i > MSG_IN_QUEUE_SIZE - n) | 
 | 445 |           i = MSG_IN_QUEUE_SIZE - n + 1; | 
 | 446 |         i -= j; | 
 | 447 |       } | 
 | 448 |  | 
 | 449 |       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc)) | 
 | 450 |  | 
 | 451 |       { | 
 | 452 |         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d", | 
 | 453 |           msg->header.length, plci->msg_in_write_pos, | 
 | 454 |           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i)); | 
 | 455 |  | 
 | 456 |         return _QUEUE_FULL; | 
 | 457 |       } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 458 |       c = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 459 |       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue))) | 
 | 460 |        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | 
 | 461 |       { | 
 | 462 |         if (plci->msg_in_write_pos != plci->msg_in_read_pos) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 463 |           c = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 464 |       } | 
 | 465 |       if (msg->header.command == _DATA_B3_R) | 
 | 466 |       { | 
 | 467 |         if (msg->header.length < 20) | 
 | 468 |         { | 
 | 469 |           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length)); | 
 | 470 |           return _BAD_MSG; | 
 | 471 |         } | 
 | 472 |         ncci_ptr = &(a->ncci[ncci]); | 
 | 473 |         n = ncci_ptr->data_pending; | 
 | 474 |         l = ncci_ptr->data_ack_pending; | 
 | 475 |         k = plci->msg_in_read_pos; | 
 | 476 |         while (k != plci->msg_in_write_pos) | 
 | 477 |         { | 
 | 478 |           if (k == plci->msg_in_wrap_pos) | 
 | 479 |             k = 0; | 
 | 480 |           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R) | 
 | 481 |            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci)) | 
 | 482 |           { | 
 | 483 |             n++; | 
 | 484 |             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004) | 
 | 485 |               l++; | 
 | 486 |           } | 
 | 487 |  | 
 | 488 |           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length + | 
 | 489 |             MSG_IN_OVERHEAD + 3) & 0xfffc; | 
 | 490 |  | 
 | 491 |         } | 
 | 492 |         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK)) | 
 | 493 |         { | 
 | 494 |           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d", | 
 | 495 |                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l)); | 
 | 496 |  | 
 | 497 |           return _QUEUE_FULL; | 
 | 498 |         } | 
 | 499 |         if (plci->req_in || plci->internal_command) | 
 | 500 |         { | 
 | 501 |           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue))) | 
 | 502 |            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | 
 | 503 |           { | 
 | 504 |             dbug(0,dprintf("Q-FULL3(requeue)")); | 
 | 505 |  | 
 | 506 |             return _QUEUE_FULL; | 
 | 507 |           } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 508 |           c = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 509 |         } | 
 | 510 |       } | 
 | 511 |       else | 
 | 512 |       { | 
 | 513 |         if (plci->req_in || plci->internal_command) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 514 |           c = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 515 |         else | 
 | 516 |         { | 
 | 517 |           plci->command = msg->header.command; | 
 | 518 |           plci->number = msg->header.number; | 
 | 519 |         } | 
 | 520 |       } | 
 | 521 |       if (c) | 
 | 522 |       { | 
 | 523 |         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d", | 
 | 524 |           msg->header.command, plci->req_in, plci->internal_command, | 
 | 525 |           msg->header.length, plci->msg_in_write_pos, | 
 | 526 |           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i)); | 
 | 527 |         if (j == 0) | 
 | 528 |           plci->msg_in_wrap_pos = plci->msg_in_write_pos; | 
 | 529 |         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]); | 
 | 530 |         for (i = 0; i < msg->header.length; i++) | 
 | 531 |           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i]; | 
 | 532 |         if (m->header.command == _DATA_B3_R) | 
 | 533 |         { | 
 | 534 |  | 
| Andrew Morton | d3c8bdf | 2007-05-23 13:58:22 -0700 | [diff] [blame] | 535 |           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 536 |  | 
 | 537 |         } | 
 | 538 |  | 
 | 539 |         j = (j + 3) & 0xfffc; | 
 | 540 |  | 
 | 541 |         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl; | 
 | 542 |         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD; | 
 | 543 |         return 0; | 
 | 544 |       } | 
 | 545 |     } | 
 | 546 |     else | 
 | 547 |     { | 
 | 548 |       plci = NULL; | 
 | 549 |     } | 
 | 550 |   } | 
 | 551 |   dbug(1,dprintf("com=%x",msg->header.command)); | 
 | 552 |  | 
 | 553 |   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0; | 
| Karsten Keil | ba2d6cc | 2009-07-24 18:26:08 +0200 | [diff] [blame] | 554 |   for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 555 |  | 
 | 556 |     if(ftable[i].command==msg->header.command) { | 
 | 557 |       /* break loop if the message is correct, otherwise continue scan  */ | 
 | 558 |       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */ | 
 | 559 |       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) { | 
 | 560 |         ret = 0; | 
 | 561 |         break; | 
 | 562 |       } | 
 | 563 |       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0; | 
 | 564 |     } | 
 | 565 |   } | 
 | 566 |   if(ret) { | 
 | 567 |     dbug(1,dprintf("BAD_MSG")); | 
 | 568 |     if(plci) plci->command = 0; | 
 | 569 |     return ret; | 
 | 570 |   } | 
 | 571 |  | 
 | 572 |  | 
 | 573 |   c = ftable[i].function(GET_DWORD(&msg->header.controller), | 
 | 574 |                          msg->header.number, | 
 | 575 |                          a, | 
 | 576 |                          plci, | 
 | 577 |                          appl, | 
 | 578 |                          msg_parms); | 
 | 579 |  | 
 | 580 |   channel_xmit_extended_xon (plci); | 
 | 581 |  | 
 | 582 |   if(c==1) send_req(plci); | 
 | 583 |   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0; | 
 | 584 |   if(plci && !plci->req_in) plci->command = 0; | 
 | 585 |   return 0; | 
 | 586 | } | 
 | 587 |  | 
 | 588 |  | 
 | 589 | /*------------------------------------------------------------------*/ | 
 | 590 | /* api_parse function, check the format of api messages             */ | 
 | 591 | /*------------------------------------------------------------------*/ | 
 | 592 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 593 | static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 594 | { | 
 | 595 |   word i; | 
 | 596 |   word p; | 
 | 597 |  | 
 | 598 |   for(i=0,p=0; format[i]; i++) { | 
 | 599 |     if(parms) | 
 | 600 |     { | 
 | 601 |       parms[i].info = &msg[p]; | 
 | 602 |     } | 
 | 603 |     switch(format[i]) { | 
 | 604 |     case 'b': | 
 | 605 |       p +=1; | 
 | 606 |       break; | 
 | 607 |     case 'w': | 
 | 608 |       p +=2; | 
 | 609 |       break; | 
 | 610 |     case 'd': | 
 | 611 |       p +=4; | 
 | 612 |       break; | 
 | 613 |     case 's': | 
 | 614 |       if(msg[p]==0xff) { | 
 | 615 |         parms[i].info +=2; | 
 | 616 |         parms[i].length = msg[p+1] + (msg[p+2]<<8); | 
 | 617 |         p +=(parms[i].length +3); | 
 | 618 |       } | 
 | 619 |       else { | 
 | 620 |         parms[i].length = msg[p]; | 
 | 621 |         p +=(parms[i].length +1); | 
 | 622 |       } | 
 | 623 |       break; | 
 | 624 |     } | 
 | 625 |  | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 626 |     if(p>length) return true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 627 |   } | 
 | 628 |   if(parms) parms[i].info = NULL; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 629 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 630 | } | 
 | 631 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 632 | static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 633 | { | 
 | 634 |   word i, j, n = 0; | 
 | 635 |   byte   *p; | 
 | 636 |  | 
 | 637 |   p = out->info; | 
 | 638 |   for (i = 0; format[i] != '\0'; i++) | 
 | 639 |   { | 
 | 640 |     out->parms[i].info = p; | 
 | 641 |     out->parms[i].length = in[i].length; | 
 | 642 |     switch (format[i]) | 
 | 643 |     { | 
 | 644 |     case 'b': | 
 | 645 |       n = 1; | 
 | 646 |       break; | 
 | 647 |     case 'w': | 
 | 648 |       n = 2; | 
 | 649 |       break; | 
 | 650 |     case 'd': | 
 | 651 |       n = 4; | 
 | 652 |       break; | 
 | 653 |     case 's': | 
 | 654 |       n = in[i].length + 1; | 
 | 655 |       break; | 
 | 656 |     } | 
 | 657 |     for (j = 0; j < n; j++) | 
 | 658 |       *(p++) = in[i].info[j]; | 
 | 659 |   } | 
 | 660 |   out->parms[i].info = NULL; | 
 | 661 |   out->parms[i].length = 0; | 
 | 662 | } | 
 | 663 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 664 | static void api_load_msg(API_SAVE *in, API_PARSE *out) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 665 | { | 
 | 666 |   word i; | 
 | 667 |  | 
 | 668 |   i = 0; | 
 | 669 |   do | 
 | 670 |   { | 
 | 671 |     out[i].info = in->parms[i].info; | 
 | 672 |     out[i].length = in->parms[i].length; | 
 | 673 |   } while (in->parms[i++].info); | 
 | 674 | } | 
 | 675 |  | 
 | 676 |  | 
 | 677 | /*------------------------------------------------------------------*/ | 
 | 678 | /* CAPI remove function                                             */ | 
 | 679 | /*------------------------------------------------------------------*/ | 
 | 680 |  | 
 | 681 | word api_remove_start(void) | 
 | 682 | { | 
 | 683 |   word i; | 
 | 684 |   word j; | 
 | 685 |  | 
 | 686 |   if(!remove_started) { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 687 |     remove_started = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 688 |     for(i=0;i<max_adapter;i++) { | 
 | 689 |       if(adapter[i].request) { | 
 | 690 |         for(j=0;j<adapter[i].max_plci;j++) { | 
 | 691 |           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]); | 
 | 692 |         } | 
 | 693 |       } | 
 | 694 |     } | 
 | 695 |     return 1; | 
 | 696 |   } | 
 | 697 |   else { | 
 | 698 |     for(i=0;i<max_adapter;i++) { | 
 | 699 |       if(adapter[i].request) { | 
 | 700 |         for(j=0;j<adapter[i].max_plci;j++) { | 
 | 701 |           if(adapter[i].plci[j].Sig.Id) return 1; | 
 | 702 |         } | 
 | 703 |       } | 
 | 704 |     } | 
 | 705 |   } | 
 | 706 |   api_remove_complete(); | 
 | 707 |   return 0; | 
 | 708 | } | 
 | 709 |  | 
 | 710 |  | 
 | 711 | /*------------------------------------------------------------------*/ | 
 | 712 | /* internal command queue                                           */ | 
 | 713 | /*------------------------------------------------------------------*/ | 
 | 714 |  | 
 | 715 | static void init_internal_command_queue (PLCI   *plci) | 
 | 716 | { | 
 | 717 |   word i; | 
 | 718 |  | 
 | 719 |   dbug (1, dprintf ("%s,%d: init_internal_command_queue", | 
 | 720 |     (char   *)(FILE_), __LINE__)); | 
 | 721 |  | 
 | 722 |   plci->internal_command = 0; | 
 | 723 |   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++) | 
 | 724 |     plci->internal_command_queue[i] = NULL; | 
 | 725 | } | 
 | 726 |  | 
 | 727 |  | 
 | 728 | static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function) | 
 | 729 | { | 
 | 730 |   word i; | 
 | 731 |  | 
 | 732 |   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command", | 
 | 733 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 734 |  | 
 | 735 |   if (plci->internal_command == 0) | 
 | 736 |   { | 
 | 737 |     plci->internal_command_queue[0] = command_function; | 
 | 738 |     (* command_function)(Id, plci, OK); | 
 | 739 |   } | 
 | 740 |   else | 
 | 741 |   { | 
 | 742 |     i = 1; | 
| Harvey Harrison | dd58c0d | 2008-04-28 02:14:39 -0700 | [diff] [blame] | 743 |     while (plci->internal_command_queue[i] != NULL) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 744 |       i++; | 
 | 745 |     plci->internal_command_queue[i] = command_function; | 
 | 746 |   } | 
 | 747 | } | 
 | 748 |  | 
 | 749 |  | 
 | 750 | static void next_internal_command (dword Id, PLCI   *plci) | 
 | 751 | { | 
 | 752 |   word i; | 
 | 753 |  | 
 | 754 |   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command", | 
 | 755 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 756 |  | 
 | 757 |   plci->internal_command = 0; | 
 | 758 |   plci->internal_command_queue[0] = NULL; | 
| Harvey Harrison | dd58c0d | 2008-04-28 02:14:39 -0700 | [diff] [blame] | 759 |   while (plci->internal_command_queue[1] != NULL) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 760 |   { | 
 | 761 |     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++) | 
 | 762 |       plci->internal_command_queue[i] = plci->internal_command_queue[i+1]; | 
 | 763 |     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL; | 
 | 764 |     (*(plci->internal_command_queue[0]))(Id, plci, OK); | 
 | 765 |     if (plci->internal_command != 0) | 
 | 766 |       return; | 
 | 767 |     plci->internal_command_queue[0] = NULL; | 
 | 768 |   } | 
 | 769 | } | 
 | 770 |  | 
 | 771 |  | 
 | 772 | /*------------------------------------------------------------------*/ | 
 | 773 | /* NCCI allocate/remove function                                    */ | 
 | 774 | /*------------------------------------------------------------------*/ | 
 | 775 |  | 
 | 776 | static dword ncci_mapping_bug = 0; | 
 | 777 |  | 
 | 778 | static word get_ncci (PLCI   *plci, byte ch, word force_ncci) | 
 | 779 | { | 
 | 780 |   DIVA_CAPI_ADAPTER   *a; | 
 | 781 |   word ncci, i, j, k; | 
 | 782 |  | 
 | 783 |   a = plci->adapter; | 
 | 784 |   if (!ch || a->ch_ncci[ch]) | 
 | 785 |   { | 
 | 786 |     ncci_mapping_bug++; | 
 | 787 |     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x", | 
 | 788 |       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch])); | 
 | 789 |     ncci = ch; | 
 | 790 |   } | 
 | 791 |   else | 
 | 792 |   { | 
 | 793 |     if (force_ncci) | 
 | 794 |       ncci = force_ncci; | 
 | 795 |     else | 
 | 796 |     { | 
 | 797 |       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch]) | 
 | 798 |         ncci = ch; | 
 | 799 |       else | 
 | 800 |       { | 
 | 801 |         ncci = 1; | 
 | 802 |         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci]) | 
 | 803 |           ncci++; | 
 | 804 |         if (ncci == MAX_NCCI+1) | 
 | 805 |         { | 
 | 806 |           ncci_mapping_bug++; | 
 | 807 |           i = 1; | 
 | 808 |           do | 
 | 809 |           { | 
 | 810 |             j = 1; | 
 | 811 |             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i)) | 
 | 812 |               j++; | 
 | 813 |             k = j; | 
 | 814 |             if (j < MAX_NCCI+1) | 
 | 815 |             { | 
 | 816 |               do | 
 | 817 |               { | 
 | 818 |                 j++; | 
 | 819 |               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i)); | 
 | 820 |             } | 
 | 821 |           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1)); | 
 | 822 |           if (i < MAX_NL_CHANNEL+1) | 
 | 823 |           { | 
 | 824 |             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x", | 
 | 825 |               ncci_mapping_bug, ch, force_ncci, i, k, j)); | 
 | 826 |           } | 
 | 827 |           else | 
 | 828 |           { | 
 | 829 |             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x", | 
 | 830 |               ncci_mapping_bug, ch, force_ncci)); | 
 | 831 |           } | 
 | 832 |           ncci = ch; | 
 | 833 |         } | 
 | 834 |       } | 
 | 835 |       a->ncci_plci[ncci] = plci->Id; | 
 | 836 |       a->ncci_state[ncci] = IDLE; | 
 | 837 |       if (!plci->ncci_ring_list) | 
 | 838 |         plci->ncci_ring_list = ncci; | 
 | 839 |       else | 
 | 840 |         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list]; | 
 | 841 |       a->ncci_next[plci->ncci_ring_list] = (byte) ncci; | 
 | 842 |     } | 
 | 843 |     a->ncci_ch[ncci] = ch; | 
 | 844 |     a->ch_ncci[ch] = (byte) ncci; | 
 | 845 |     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x", | 
 | 846 |       ncci_mapping_bug, ch, force_ncci, ch, ncci)); | 
 | 847 |   } | 
 | 848 |   return (ncci); | 
 | 849 | } | 
 | 850 |  | 
 | 851 |  | 
 | 852 | static void ncci_free_receive_buffers (PLCI   *plci, word ncci) | 
 | 853 | { | 
 | 854 |   DIVA_CAPI_ADAPTER   *a; | 
 | 855 |   APPL   *appl; | 
 | 856 |   word i, ncci_code; | 
 | 857 |   dword Id; | 
 | 858 |  | 
 | 859 |   a = plci->adapter; | 
 | 860 |   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id; | 
 | 861 |   if (ncci) | 
 | 862 |   { | 
 | 863 |     if (a->ncci_plci[ncci] == plci->Id) | 
 | 864 |     { | 
 | 865 |       if (!plci->appl) | 
 | 866 |       { | 
 | 867 |         ncci_mapping_bug++; | 
 | 868 |         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx", | 
 | 869 |           ncci_mapping_bug, Id)); | 
 | 870 |       } | 
 | 871 |       else | 
 | 872 |       { | 
 | 873 |         appl = plci->appl; | 
 | 874 |         ncci_code = ncci | (((word) a->Id) << 8); | 
 | 875 |         for (i = 0; i < appl->MaxBuffer; i++) | 
 | 876 |         { | 
 | 877 |           if ((appl->DataNCCI[i] == ncci_code) | 
 | 878 |            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id)) | 
 | 879 |           { | 
 | 880 |             appl->DataNCCI[i] = 0; | 
 | 881 |           } | 
 | 882 |         } | 
 | 883 |       } | 
 | 884 |     } | 
 | 885 |   } | 
 | 886 |   else | 
 | 887 |   { | 
 | 888 |     for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | 
 | 889 |     { | 
 | 890 |       if (a->ncci_plci[ncci] == plci->Id) | 
 | 891 |       { | 
 | 892 |         if (!plci->appl) | 
 | 893 |         { | 
 | 894 |           ncci_mapping_bug++; | 
 | 895 |           dbug(1,dprintf("NCCI mapping no appl %ld %08lx", | 
 | 896 |             ncci_mapping_bug, Id)); | 
 | 897 |         } | 
 | 898 |         else | 
 | 899 |         { | 
 | 900 |           appl = plci->appl; | 
 | 901 |           ncci_code = ncci | (((word) a->Id) << 8); | 
 | 902 |           for (i = 0; i < appl->MaxBuffer; i++) | 
 | 903 |           { | 
 | 904 |             if ((appl->DataNCCI[i] == ncci_code) | 
 | 905 |              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id)) | 
 | 906 |             { | 
 | 907 |               appl->DataNCCI[i] = 0; | 
 | 908 |             } | 
 | 909 |           } | 
 | 910 |         } | 
 | 911 |       } | 
 | 912 |     } | 
 | 913 |   } | 
 | 914 | } | 
 | 915 |  | 
 | 916 |  | 
 | 917 | static void cleanup_ncci_data (PLCI   *plci, word ncci) | 
 | 918 | { | 
 | 919 |   NCCI   *ncci_ptr; | 
 | 920 |  | 
 | 921 |   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id)) | 
 | 922 |   { | 
 | 923 |     ncci_ptr = &(plci->adapter->ncci[ncci]); | 
 | 924 |     if (plci->appl) | 
 | 925 |     { | 
 | 926 |       while (ncci_ptr->data_pending != 0) | 
 | 927 |       { | 
 | 928 |         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr)) | 
 | 929 |           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P); | 
 | 930 |         (ncci_ptr->data_out)++; | 
 | 931 |         if (ncci_ptr->data_out == MAX_DATA_B3) | 
 | 932 |           ncci_ptr->data_out = 0; | 
 | 933 |         (ncci_ptr->data_pending)--; | 
 | 934 |       } | 
 | 935 |     } | 
 | 936 |     ncci_ptr->data_out = 0; | 
 | 937 |     ncci_ptr->data_pending = 0; | 
 | 938 |     ncci_ptr->data_ack_out = 0; | 
 | 939 |     ncci_ptr->data_ack_pending = 0; | 
 | 940 |   } | 
 | 941 | } | 
 | 942 |  | 
 | 943 |  | 
 | 944 | static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci) | 
 | 945 | { | 
 | 946 |   DIVA_CAPI_ADAPTER   *a; | 
 | 947 |   dword Id; | 
 | 948 |   word i; | 
 | 949 |  | 
 | 950 |   a = plci->adapter; | 
 | 951 |   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id; | 
 | 952 |   if (!preserve_ncci) | 
 | 953 |     ncci_free_receive_buffers (plci, ncci); | 
 | 954 |   if (ncci) | 
 | 955 |   { | 
 | 956 |     if (a->ncci_plci[ncci] != plci->Id) | 
 | 957 |     { | 
 | 958 |       ncci_mapping_bug++; | 
 | 959 |       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x", | 
 | 960 |         ncci_mapping_bug, Id, preserve_ncci)); | 
 | 961 |     } | 
 | 962 |     else | 
 | 963 |     { | 
 | 964 |       cleanup_ncci_data (plci, ncci); | 
 | 965 |       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x", | 
 | 966 |         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci)); | 
 | 967 |       a->ch_ncci[a->ncci_ch[ncci]] = 0; | 
 | 968 |       if (!preserve_ncci) | 
 | 969 |       { | 
 | 970 |         a->ncci_ch[ncci] = 0; | 
 | 971 |         a->ncci_plci[ncci] = 0; | 
 | 972 |         a->ncci_state[ncci] = IDLE; | 
 | 973 |         i = plci->ncci_ring_list; | 
 | 974 |         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci)) | 
 | 975 |           i = a->ncci_next[i]; | 
 | 976 |         if ((i != 0) && (a->ncci_next[i] == ncci)) | 
 | 977 |         { | 
 | 978 |           if (i == ncci) | 
 | 979 |             plci->ncci_ring_list = 0; | 
 | 980 |           else if (plci->ncci_ring_list == ncci) | 
 | 981 |             plci->ncci_ring_list = i; | 
 | 982 |           a->ncci_next[i] = a->ncci_next[ncci]; | 
 | 983 |         } | 
 | 984 |         a->ncci_next[ncci] = 0; | 
 | 985 |       } | 
 | 986 |     } | 
 | 987 |   } | 
 | 988 |   else | 
 | 989 |   { | 
 | 990 |     for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | 
 | 991 |     { | 
 | 992 |       if (a->ncci_plci[ncci] == plci->Id) | 
 | 993 |       { | 
 | 994 |         cleanup_ncci_data (plci, ncci); | 
 | 995 |         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x", | 
 | 996 |           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci)); | 
 | 997 |         a->ch_ncci[a->ncci_ch[ncci]] = 0; | 
 | 998 |         if (!preserve_ncci) | 
 | 999 |         { | 
 | 1000 |           a->ncci_ch[ncci] = 0; | 
 | 1001 |           a->ncci_plci[ncci] = 0; | 
 | 1002 |           a->ncci_state[ncci] = IDLE; | 
 | 1003 |           a->ncci_next[ncci] = 0; | 
 | 1004 |         } | 
 | 1005 |       } | 
 | 1006 |     } | 
 | 1007 |     if (!preserve_ncci) | 
 | 1008 |       plci->ncci_ring_list = 0; | 
 | 1009 |   } | 
 | 1010 | } | 
 | 1011 |  | 
 | 1012 |  | 
 | 1013 | /*------------------------------------------------------------------*/ | 
 | 1014 | /* PLCI remove function                                             */ | 
 | 1015 | /*------------------------------------------------------------------*/ | 
 | 1016 |  | 
 | 1017 | static void plci_free_msg_in_queue (PLCI   *plci) | 
 | 1018 | { | 
 | 1019 |   word i; | 
 | 1020 |  | 
 | 1021 |   if (plci->appl) | 
 | 1022 |   { | 
 | 1023 |     i = plci->msg_in_read_pos; | 
 | 1024 |     while (i != plci->msg_in_write_pos) | 
 | 1025 |     { | 
 | 1026 |       if (i == plci->msg_in_wrap_pos) | 
 | 1027 |         i = 0; | 
 | 1028 |       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R) | 
 | 1029 |       { | 
 | 1030 |  | 
 | 1031 |         TransmitBufferFree (plci->appl, | 
| Andrew Morton | d3c8bdf | 2007-05-23 13:58:22 -0700 | [diff] [blame] | 1032 |           (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1033 |  | 
 | 1034 |       } | 
 | 1035 |  | 
 | 1036 |       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length + | 
 | 1037 |         MSG_IN_OVERHEAD + 3) & 0xfffc; | 
 | 1038 |  | 
 | 1039 |     } | 
 | 1040 |   } | 
 | 1041 |   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE; | 
 | 1042 |   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | 
 | 1043 |   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | 
 | 1044 | } | 
 | 1045 |  | 
 | 1046 |  | 
 | 1047 | static void plci_remove(PLCI   * plci) | 
 | 1048 | { | 
 | 1049 |  | 
 | 1050 |   if(!plci) { | 
 | 1051 |     dbug(1,dprintf("plci_remove(no plci)")); | 
 | 1052 |     return; | 
 | 1053 |   } | 
 | 1054 |   init_internal_command_queue (plci); | 
 | 1055 |   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel)); | 
 | 1056 |   if(plci_remove_check(plci)) | 
 | 1057 |   { | 
 | 1058 |     return; | 
 | 1059 |   } | 
 | 1060 |   if (plci->Sig.Id == 0xff) | 
 | 1061 |   { | 
 | 1062 |     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id)); | 
 | 1063 |     if (plci->NL.Id && !plci->nl_remove_id) | 
 | 1064 |     { | 
 | 1065 |       nl_req_ncci(plci,REMOVE,0); | 
 | 1066 |       send_req(plci); | 
 | 1067 |     } | 
 | 1068 |   } | 
 | 1069 |   else | 
 | 1070 |   { | 
 | 1071 |     if (!plci->sig_remove_id | 
 | 1072 |      && (plci->Sig.Id | 
 | 1073 |       || (plci->req_in!=plci->req_out) | 
 | 1074 |       || (plci->nl_req || plci->sig_req))) | 
 | 1075 |     { | 
 | 1076 |       sig_req(plci,HANGUP,0); | 
 | 1077 |       send_req(plci); | 
 | 1078 |     } | 
 | 1079 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1080 |   ncci_remove (plci, 0, false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1081 |   plci_free_msg_in_queue (plci); | 
 | 1082 |  | 
 | 1083 |   plci->channels = 0; | 
 | 1084 |   plci->appl = NULL; | 
 | 1085 |   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) | 
 | 1086 |     plci->State = OUTG_DIS_PENDING; | 
 | 1087 | } | 
 | 1088 |  | 
 | 1089 | /*------------------------------------------------------------------*/ | 
 | 1090 | /* Application Group function helpers                               */ | 
 | 1091 | /*------------------------------------------------------------------*/ | 
 | 1092 |  | 
 | 1093 | static void set_group_ind_mask (PLCI   *plci) | 
 | 1094 | { | 
 | 1095 |   word i; | 
 | 1096 |  | 
 | 1097 |   for (i = 0; i < C_IND_MASK_DWORDS; i++) | 
 | 1098 |     plci->group_optimization_mask_table[i] = 0xffffffffL; | 
 | 1099 | } | 
 | 1100 |  | 
 | 1101 | static void clear_group_ind_mask_bit (PLCI   *plci, word b) | 
 | 1102 | { | 
 | 1103 |   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f)); | 
 | 1104 | } | 
 | 1105 |  | 
 | 1106 | static byte test_group_ind_mask_bit (PLCI   *plci, word b) | 
 | 1107 | { | 
 | 1108 |   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0); | 
 | 1109 | } | 
 | 1110 |  | 
 | 1111 | /*------------------------------------------------------------------*/ | 
 | 1112 | /* c_ind_mask operations for arbitrary MAX_APPL                     */ | 
 | 1113 | /*------------------------------------------------------------------*/ | 
 | 1114 |  | 
 | 1115 | static void clear_c_ind_mask (PLCI   *plci) | 
 | 1116 | { | 
 | 1117 |   word i; | 
 | 1118 |  | 
 | 1119 |   for (i = 0; i < C_IND_MASK_DWORDS; i++) | 
 | 1120 |     plci->c_ind_mask_table[i] = 0; | 
 | 1121 | } | 
 | 1122 |  | 
 | 1123 | static byte c_ind_mask_empty (PLCI   *plci) | 
 | 1124 | { | 
 | 1125 |   word i; | 
 | 1126 |  | 
 | 1127 |   i = 0; | 
 | 1128 |   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0)) | 
 | 1129 |     i++; | 
 | 1130 |   return (i == C_IND_MASK_DWORDS); | 
 | 1131 | } | 
 | 1132 |  | 
 | 1133 | static void set_c_ind_mask_bit (PLCI   *plci, word b) | 
 | 1134 | { | 
 | 1135 |   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f)); | 
 | 1136 | } | 
 | 1137 |  | 
 | 1138 | static void clear_c_ind_mask_bit (PLCI   *plci, word b) | 
 | 1139 | { | 
 | 1140 |   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f)); | 
 | 1141 | } | 
 | 1142 |  | 
 | 1143 | static byte test_c_ind_mask_bit (PLCI   *plci, word b) | 
 | 1144 | { | 
 | 1145 |   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0); | 
 | 1146 | } | 
 | 1147 |  | 
 | 1148 | static void dump_c_ind_mask (PLCI   *plci) | 
 | 1149 | { | 
 | 1150 | static char hex_digit_table[0x10] = | 
 | 1151 |   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; | 
 | 1152 |   word i, j, k; | 
 | 1153 |   dword d; | 
 | 1154 |     char *p; | 
 | 1155 |     char buf[40]; | 
 | 1156 |  | 
 | 1157 |   for (i = 0; i < C_IND_MASK_DWORDS; i += 4) | 
 | 1158 |   { | 
 | 1159 |     p = buf + 36; | 
 | 1160 |     *p = '\0'; | 
 | 1161 |     for (j = 0; j < 4; j++) | 
 | 1162 |     { | 
 | 1163 |       if (i+j < C_IND_MASK_DWORDS) | 
 | 1164 |       { | 
 | 1165 |         d = plci->c_ind_mask_table[i+j]; | 
 | 1166 |         for (k = 0; k < 8; k++) | 
 | 1167 |         { | 
 | 1168 |           *(--p) = hex_digit_table[d & 0xf]; | 
 | 1169 |           d >>= 4; | 
 | 1170 |         } | 
 | 1171 |       } | 
 | 1172 |       else if (i != 0) | 
 | 1173 |       { | 
 | 1174 |         for (k = 0; k < 8; k++) | 
 | 1175 |           *(--p) = ' '; | 
 | 1176 |       } | 
 | 1177 |       *(--p) = ' '; | 
 | 1178 |     } | 
 | 1179 |     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p)); | 
 | 1180 |   } | 
 | 1181 | } | 
 | 1182 |  | 
 | 1183 |  | 
 | 1184 |  | 
 | 1185 |  | 
 | 1186 |  | 
 | 1187 | #define dump_plcis(a) | 
 | 1188 |  | 
 | 1189 |  | 
 | 1190 |  | 
 | 1191 | /*------------------------------------------------------------------*/ | 
 | 1192 | /* translation function for each message                            */ | 
 | 1193 | /*------------------------------------------------------------------*/ | 
 | 1194 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1195 | static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1196 | 			PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1197 | { | 
 | 1198 |   word ch; | 
 | 1199 |   word i; | 
 | 1200 |   word Info; | 
 | 1201 |   word CIP; | 
 | 1202 |   byte LinkLayer; | 
 | 1203 |   API_PARSE * ai; | 
 | 1204 |   API_PARSE * bp; | 
 | 1205 |     API_PARSE ai_parms[5]; | 
 | 1206 |   word channel = 0; | 
 | 1207 |   dword ch_mask; | 
 | 1208 |   byte m; | 
 | 1209 |   static byte esc_chi[35] = {0x02,0x18,0x01}; | 
 | 1210 |   static byte lli[2] = {0x01,0x00}; | 
 | 1211 |   byte noCh = 0; | 
 | 1212 |   word dir = 0; | 
 | 1213 |   byte   *p_chi = ""; | 
 | 1214 |  | 
 | 1215 |   for(i=0;i<5;i++) ai_parms[i].length = 0; | 
 | 1216 |  | 
 | 1217 |   dbug(1,dprintf("connect_req(%d)",parms->length)); | 
 | 1218 |   Info = _WRONG_IDENTIFIER; | 
 | 1219 |   if(a) | 
 | 1220 |   { | 
 | 1221 |     if(a->adapter_disabled) | 
 | 1222 |     { | 
 | 1223 |       dbug(1,dprintf("adapter disabled")); | 
 | 1224 |       Id = ((word)1<<8)|a->Id; | 
 | 1225 |       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0); | 
 | 1226 |       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1227 |       return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1228 |     } | 
 | 1229 |     Info = _OUT_OF_PLCI; | 
 | 1230 |     if((i=get_plci(a))) | 
 | 1231 |     { | 
 | 1232 |       Info = 0; | 
 | 1233 |       plci = &a->plci[i-1]; | 
 | 1234 |       plci->appl = appl; | 
 | 1235 |       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | 
 | 1236 |       /* check 'external controller' bit for codec support */ | 
 | 1237 |       if(Id & EXT_CONTROLLER) | 
 | 1238 |       { | 
 | 1239 |         if(AdvCodecSupport(a, plci, appl, 0) ) | 
 | 1240 |         { | 
 | 1241 |           plci->Id = 0; | 
 | 1242 |           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER); | 
 | 1243 |           return 2; | 
 | 1244 |         } | 
 | 1245 |       } | 
 | 1246 |       ai = &parms[9]; | 
 | 1247 |       bp = &parms[5]; | 
 | 1248 |       ch = 0; | 
 | 1249 |       if(bp->length)LinkLayer = bp->info[3]; | 
 | 1250 |       else LinkLayer = 0; | 
 | 1251 |       if(ai->length) | 
 | 1252 |       { | 
 | 1253 |         ch=0xffff; | 
 | 1254 |         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms)) | 
 | 1255 |         { | 
 | 1256 |           ch = 0; | 
 | 1257 |           if(ai_parms[0].length) | 
 | 1258 |           { | 
 | 1259 |             ch = GET_WORD(ai_parms[0].info+1); | 
 | 1260 |             if(ch>4) ch=0; /* safety -> ignore ChannelID */ | 
 | 1261 |             if(ch==4) /* explizit CHI in message */ | 
 | 1262 |             { | 
 | 1263 |               /* check length of B-CH struct */ | 
 | 1264 |               if((ai_parms[0].info)[3]>=1) | 
 | 1265 |               { | 
 | 1266 |                 if((ai_parms[0].info)[4]==CHI) | 
 | 1267 |                 { | 
 | 1268 |                   p_chi = &((ai_parms[0].info)[5]); | 
 | 1269 |                 } | 
 | 1270 |                 else | 
 | 1271 |                 { | 
 | 1272 |                   p_chi = &((ai_parms[0].info)[3]); | 
 | 1273 |                 } | 
 | 1274 |                 if(p_chi[0]>35) /* check length of channel ID */ | 
 | 1275 |                 { | 
 | 1276 |                   Info = _WRONG_MESSAGE_FORMAT;     | 
 | 1277 |                 } | 
 | 1278 |               } | 
 | 1279 |               else Info = _WRONG_MESSAGE_FORMAT;     | 
 | 1280 |             } | 
 | 1281 |  | 
 | 1282 |             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36) | 
 | 1283 |             { | 
 | 1284 |               dir = GET_WORD(ai_parms[0].info+3); | 
 | 1285 |               ch_mask = 0; | 
 | 1286 |               m = 0x3f; | 
 | 1287 |               for(i=0; i+5<=ai_parms[0].length; i++) | 
 | 1288 |               { | 
 | 1289 |                 if(ai_parms[0].info[i+5]!=0) | 
 | 1290 |                 { | 
 | 1291 |                   if((ai_parms[0].info[i+5] | m) != 0xff) | 
 | 1292 |                     Info = _WRONG_MESSAGE_FORMAT; | 
 | 1293 |                   else | 
 | 1294 |                   { | 
 | 1295 |                     if (ch_mask == 0) | 
 | 1296 |                       channel = i; | 
 | 1297 |                     ch_mask |= 1L << i; | 
 | 1298 |                   } | 
 | 1299 |                 } | 
 | 1300 |                 m = 0; | 
 | 1301 |               } | 
 | 1302 |               if (ch_mask == 0) | 
 | 1303 |                 Info = _WRONG_MESSAGE_FORMAT; | 
 | 1304 |               if (!Info) | 
 | 1305 |               { | 
 | 1306 |                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel)))) | 
 | 1307 |                 { | 
 | 1308 |                   esc_chi[0] = (byte)(ai_parms[0].length - 2); | 
 | 1309 |                   for(i=0; i+5<=ai_parms[0].length; i++) | 
 | 1310 |                     esc_chi[i+3] = ai_parms[0].info[i+5]; | 
 | 1311 |                 } | 
 | 1312 |                 else | 
 | 1313 |                   esc_chi[0] = 2; | 
 | 1314 |                 esc_chi[2] = (byte)channel; | 
 | 1315 |                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */ | 
 | 1316 |                 add_p(plci,LLI,lli); | 
 | 1317 |                 add_p(plci,ESC,esc_chi); | 
 | 1318 |                 plci->State = LOCAL_CONNECT; | 
 | 1319 |                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */ | 
 | 1320 |               } | 
 | 1321 |             } | 
 | 1322 |           } | 
 | 1323 |         } | 
 | 1324 |         else  Info = _WRONG_MESSAGE_FORMAT; | 
 | 1325 |       } | 
 | 1326 |  | 
 | 1327 |       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel)); | 
 | 1328 |       plci->command = _CONNECT_R; | 
 | 1329 |       plci->number = Number; | 
 | 1330 |       /* x.31 or D-ch free SAPI in LinkLayer? */ | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1331 |       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1332 |       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info) | 
 | 1333 |       { | 
 | 1334 |         /* B-channel used for B3 connections (ch==0), or no B channel    */ | 
 | 1335 |         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */ | 
 | 1336 |         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */ | 
 | 1337 |         else     Info = add_b1(plci,&parms[5],ch,0);  | 
 | 1338 |         add_s(plci,OAD,&parms[2]); | 
 | 1339 |         add_s(plci,OSA,&parms[4]); | 
 | 1340 |         add_s(plci,BC,&parms[6]); | 
 | 1341 |         add_s(plci,LLC,&parms[7]); | 
 | 1342 |         add_s(plci,HLC,&parms[8]); | 
 | 1343 |         CIP = GET_WORD(parms[0].info); | 
 | 1344 |         if (a->Info_Mask[appl->Id-1] & 0x200) | 
 | 1345 |         { | 
 | 1346 |           /* early B3 connect (CIP mask bit 9) no release after a disc */ | 
 | 1347 |           add_p(plci,LLI,"\x01\x01"); | 
 | 1348 |         } | 
 | 1349 |         if(GET_WORD(parms[0].info)<29) { | 
 | 1350 |           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]); | 
 | 1351 |           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]); | 
 | 1352 |         } | 
 | 1353 |         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 1354 |         sig_req(plci,ASSIGN,DSIG_ID); | 
 | 1355 |       } | 
 | 1356 |       else if(ch==1) { | 
 | 1357 |  | 
 | 1358 |         /* D-Channel used for B3 connections */ | 
 | 1359 |         plci->Sig.Id = 0xff; | 
 | 1360 |         Info = 0; | 
 | 1361 |       } | 
 | 1362 |  | 
 | 1363 |       if(!Info && ch!=2 && !noCh ) { | 
 | 1364 |         Info = add_b23(plci,&parms[5]); | 
 | 1365 |         if(!Info) { | 
 | 1366 |           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0); | 
 | 1367 |         } | 
 | 1368 |       } | 
 | 1369 |  | 
 | 1370 |       if(!Info) | 
 | 1371 |       { | 
 | 1372 |         if(ch==0 || ch==2 || ch==3 || noCh || ch==4) | 
 | 1373 |         { | 
 | 1374 |           if(plci->spoofed_msg==SPOOFING_REQUIRED) | 
 | 1375 |           { | 
 | 1376 |             api_save_msg(parms, "wsssssssss", &plci->saved_msg); | 
 | 1377 |             plci->spoofed_msg = CALL_REQ; | 
 | 1378 |             plci->internal_command = BLOCK_PLCI; | 
 | 1379 |             plci->command = 0; | 
 | 1380 |             dbug(1,dprintf("Spoof")); | 
 | 1381 |             send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1382 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1383 |           } | 
 | 1384 |           if(ch==4)add_p(plci,CHI,p_chi); | 
 | 1385 |           add_s(plci,CPN,&parms[1]); | 
 | 1386 |           add_s(plci,DSA,&parms[3]); | 
 | 1387 |           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */ | 
 | 1388 |           add_ai(plci,&parms[9]); | 
 | 1389 |           if(!dir)sig_req(plci,CALL_REQ,0); | 
 | 1390 |           else | 
 | 1391 |           { | 
 | 1392 |             plci->command = PERM_LIST_REQ; | 
 | 1393 |             plci->appl = appl; | 
 | 1394 |             sig_req(plci,LISTEN_REQ,0); | 
 | 1395 |             send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1396 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1397 |           } | 
 | 1398 |         } | 
 | 1399 |         send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1400 |         return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1401 |       } | 
 | 1402 |       plci->Id = 0; | 
 | 1403 |     } | 
 | 1404 |   } | 
 | 1405 |   sendf(appl, | 
 | 1406 |         _CONNECT_R|CONFIRM, | 
 | 1407 |         Id, | 
 | 1408 |         Number, | 
 | 1409 |         "w",Info); | 
 | 1410 |   return 2; | 
 | 1411 | } | 
 | 1412 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1413 | static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1414 | 			PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1415 | { | 
 | 1416 |   word i, Info; | 
 | 1417 |   word Reject; | 
 | 1418 |   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b}; | 
 | 1419 |   static byte esc_t[] = {0x03,0x08,0x00,0x00}; | 
 | 1420 |   API_PARSE * ai; | 
 | 1421 |     API_PARSE ai_parms[5]; | 
 | 1422 |   word ch=0; | 
 | 1423 |  | 
 | 1424 |   if(!plci) { | 
 | 1425 |     dbug(1,dprintf("connect_res(no plci)")); | 
 | 1426 |     return 0;  /* no plci, no send */ | 
 | 1427 |   } | 
 | 1428 |  | 
 | 1429 |   dbug(1,dprintf("connect_res(State=0x%x)",plci->State)); | 
 | 1430 |   for(i=0;i<5;i++) ai_parms[i].length = 0; | 
 | 1431 |   ai = &parms[5]; | 
 | 1432 |   dbug(1,dprintf("ai->length=%d",ai->length)); | 
 | 1433 |  | 
 | 1434 |   if(ai->length) | 
 | 1435 |   { | 
 | 1436 |     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms)) | 
 | 1437 |     { | 
 | 1438 |       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1))); | 
 | 1439 |       ch = 0; | 
 | 1440 |       if(ai_parms[0].length) | 
 | 1441 |       { | 
 | 1442 |         ch = GET_WORD(ai_parms[0].info+1); | 
 | 1443 |         dbug(1,dprintf("BCH-I=0x%x",ch)); | 
 | 1444 |       } | 
 | 1445 |     } | 
 | 1446 |   } | 
 | 1447 |  | 
 | 1448 |   if(plci->State==INC_CON_CONNECTED_ALERT) | 
 | 1449 |   { | 
 | 1450 |     dbug(1,dprintf("Connected Alert Call_Res")); | 
 | 1451 |     if (a->Info_Mask[appl->Id-1] & 0x200) | 
 | 1452 |     { | 
 | 1453 |     /* early B3 connect (CIP mask bit 9) no release after a disc */ | 
 | 1454 |       add_p(plci,LLI,"\x01\x01"); | 
 | 1455 |     } | 
 | 1456 |     add_s(plci, CONN_NR, &parms[2]); | 
 | 1457 |     add_s(plci, LLC, &parms[4]); | 
 | 1458 |     add_ai(plci, &parms[5]); | 
 | 1459 |     plci->State = INC_CON_ACCEPT; | 
 | 1460 |     sig_req(plci, CALL_RES,0); | 
 | 1461 |     return 1; | 
 | 1462 |   } | 
 | 1463 |   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) { | 
 | 1464 |     clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | 
 | 1465 |     dump_c_ind_mask (plci); | 
 | 1466 |     Reject = GET_WORD(parms[0].info); | 
 | 1467 |     dbug(1,dprintf("Reject=0x%x",Reject)); | 
 | 1468 |     if(Reject)  | 
 | 1469 |     { | 
 | 1470 |       if(c_ind_mask_empty (plci))  | 
 | 1471 |       { | 
 | 1472 |         if((Reject&0xff00)==0x3400)  | 
 | 1473 |         { | 
 | 1474 |           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80; | 
 | 1475 |           add_p(plci,ESC,esc_t); | 
 | 1476 |           add_ai(plci, &parms[5]); | 
 | 1477 |           sig_req(plci,REJECT,0); | 
 | 1478 |         }       | 
 | 1479 |         else if(Reject==1 || Reject>9)  | 
 | 1480 |         { | 
 | 1481 |           add_ai(plci, &parms[5]); | 
 | 1482 |           sig_req(plci,HANGUP,0); | 
 | 1483 |         } | 
 | 1484 |         else  | 
 | 1485 |         { | 
 | 1486 |           esc_t[2] = cau_t[(Reject&0x000f)]; | 
 | 1487 |           add_p(plci,ESC,esc_t); | 
 | 1488 |           add_ai(plci, &parms[5]); | 
 | 1489 |           sig_req(plci,REJECT,0); | 
 | 1490 |         } | 
 | 1491 |         plci->appl = appl; | 
 | 1492 |       } | 
 | 1493 |       else  | 
 | 1494 |       { | 
 | 1495 |         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED); | 
 | 1496 |       } | 
 | 1497 |     } | 
 | 1498 |     else { | 
 | 1499 |       plci->appl = appl; | 
 | 1500 |       if(Id & EXT_CONTROLLER){ | 
 | 1501 |         if(AdvCodecSupport(a, plci, appl, 0)){ | 
 | 1502 |           dbug(1,dprintf("connect_res(error from AdvCodecSupport)")); | 
 | 1503 |           sig_req(plci,HANGUP,0); | 
 | 1504 |           return 1; | 
 | 1505 |         } | 
 | 1506 |         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI) | 
 | 1507 |         { | 
 | 1508 |           Info = add_b23(plci, &parms[1]); | 
 | 1509 |           if (Info) | 
 | 1510 |           { | 
 | 1511 |             dbug(1,dprintf("connect_res(error from add_b23)")); | 
 | 1512 |             sig_req(plci,HANGUP,0); | 
 | 1513 |             return 1; | 
 | 1514 |           } | 
 | 1515 |           if(plci->adv_nl) | 
 | 1516 |           { | 
 | 1517 |             nl_req_ncci(plci, ASSIGN, 0); | 
 | 1518 |           } | 
 | 1519 |         } | 
 | 1520 |       } | 
 | 1521 |       else | 
 | 1522 |       { | 
 | 1523 |         plci->tel = 0; | 
 | 1524 |         if(ch!=2) | 
 | 1525 |         { | 
 | 1526 |           Info = add_b23(plci, &parms[1]); | 
 | 1527 |           if (Info) | 
 | 1528 |           { | 
 | 1529 |             dbug(1,dprintf("connect_res(error from add_b23 2)")); | 
 | 1530 |             sig_req(plci,HANGUP,0); | 
 | 1531 |             return 1; | 
 | 1532 |           } | 
 | 1533 |         } | 
 | 1534 |         nl_req_ncci(plci, ASSIGN, 0); | 
 | 1535 |       } | 
 | 1536 |  | 
 | 1537 |       if(plci->spoofed_msg==SPOOFING_REQUIRED) | 
 | 1538 |       { | 
 | 1539 |         api_save_msg(parms, "wsssss", &plci->saved_msg); | 
 | 1540 |         plci->spoofed_msg = CALL_RES; | 
 | 1541 |         plci->internal_command = BLOCK_PLCI; | 
 | 1542 |         plci->command = 0; | 
 | 1543 |         dbug(1,dprintf("Spoof")); | 
 | 1544 |       } | 
 | 1545 |       else | 
 | 1546 |       { | 
 | 1547 |         add_b1 (plci, &parms[1], ch, plci->B1_facilities); | 
 | 1548 |         if (a->Info_Mask[appl->Id-1] & 0x200) | 
 | 1549 |         { | 
 | 1550 |           /* early B3 connect (CIP mask bit 9) no release after a disc */ | 
 | 1551 |           add_p(plci,LLI,"\x01\x01"); | 
 | 1552 |         } | 
 | 1553 |         add_s(plci, CONN_NR, &parms[2]); | 
 | 1554 |         add_s(plci, LLC, &parms[4]); | 
 | 1555 |         add_ai(plci, &parms[5]); | 
 | 1556 |         plci->State = INC_CON_ACCEPT; | 
 | 1557 |         sig_req(plci, CALL_RES,0); | 
 | 1558 |       } | 
 | 1559 |  | 
 | 1560 |       for(i=0; i<max_appl; i++) { | 
 | 1561 |         if(test_c_ind_mask_bit (plci, i)) { | 
 | 1562 |           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED); | 
 | 1563 |         } | 
 | 1564 |       } | 
 | 1565 |     } | 
 | 1566 |   } | 
 | 1567 |   return 1; | 
 | 1568 | } | 
 | 1569 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1570 | static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1571 | 			  PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1572 | { | 
 | 1573 |   dbug(1,dprintf("connect_a_res")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1574 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1575 | } | 
 | 1576 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1577 | static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1578 | 			   PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1579 | { | 
 | 1580 |   word Info; | 
 | 1581 |   word i; | 
 | 1582 |  | 
 | 1583 |   dbug(1,dprintf("disconnect_req")); | 
 | 1584 |  | 
 | 1585 |   Info = _WRONG_IDENTIFIER; | 
 | 1586 |  | 
 | 1587 |   if(plci) | 
 | 1588 |   { | 
 | 1589 |     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) | 
 | 1590 |     { | 
 | 1591 |       clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | 
 | 1592 |       plci->appl = appl; | 
 | 1593 |       for(i=0; i<max_appl; i++) | 
 | 1594 |       { | 
 | 1595 |         if(test_c_ind_mask_bit (plci, i)) | 
 | 1596 |           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0); | 
 | 1597 |       } | 
 | 1598 |       plci->State = OUTG_DIS_PENDING; | 
 | 1599 |     } | 
 | 1600 |     if(plci->Sig.Id && plci->appl) | 
 | 1601 |     { | 
 | 1602 |       Info = 0; | 
 | 1603 |         if(plci->Sig.Id!=0xff) | 
 | 1604 |         { | 
 | 1605 |           if(plci->State!=INC_DIS_PENDING) | 
 | 1606 |           { | 
 | 1607 |             add_ai(plci, &msg[0]); | 
 | 1608 |             sig_req(plci,HANGUP,0); | 
 | 1609 |             plci->State = OUTG_DIS_PENDING; | 
 | 1610 |             return 1; | 
 | 1611 |           } | 
 | 1612 |         } | 
 | 1613 |         else | 
 | 1614 |         { | 
 | 1615 |           if (plci->NL.Id && !plci->nl_remove_id) | 
 | 1616 |           { | 
 | 1617 |             mixer_remove (plci); | 
 | 1618 |             nl_req_ncci(plci,REMOVE,0); | 
 | 1619 |           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0); | 
 | 1620 |           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0); | 
 | 1621 |           plci->State = INC_DIS_PENDING; | 
 | 1622 |           } | 
 | 1623 |           return 1; | 
 | 1624 |         } | 
 | 1625 |       } | 
 | 1626 |     } | 
 | 1627 |  | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1628 |   if(!appl)  return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1629 |   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1630 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1631 | } | 
 | 1632 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1633 | static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1634 | 			   PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1635 | { | 
 | 1636 |   dbug(1,dprintf("disconnect_res")); | 
 | 1637 |   if(plci) | 
 | 1638 |   { | 
 | 1639 |         /* clear ind mask bit, just in case of collsion of          */ | 
 | 1640 |         /* DISCONNECT_IND and CONNECT_RES                           */ | 
 | 1641 |     clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | 
 | 1642 |     ncci_free_receive_buffers (plci, 0); | 
 | 1643 |     if(plci_remove_check(plci)) | 
 | 1644 |     { | 
 | 1645 |       return 0; | 
 | 1646 |     } | 
 | 1647 |     if(plci->State==INC_DIS_PENDING | 
 | 1648 |     || plci->State==SUSPENDING) { | 
 | 1649 |       if(c_ind_mask_empty (plci)) { | 
 | 1650 |         if(plci->State!=SUSPENDING)plci->State = IDLE; | 
 | 1651 |         dbug(1,dprintf("chs=%d",plci->channels)); | 
 | 1652 |         if(!plci->channels) { | 
 | 1653 |           plci_remove(plci); | 
 | 1654 |         } | 
 | 1655 |       } | 
 | 1656 |     } | 
 | 1657 |   } | 
 | 1658 |   return 0; | 
 | 1659 | } | 
 | 1660 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1661 | static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1662 | 		       PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1663 | { | 
 | 1664 |   word Info; | 
 | 1665 |   byte i; | 
 | 1666 |  | 
 | 1667 |   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id)); | 
 | 1668 |  | 
 | 1669 |   Info = _WRONG_IDENTIFIER; | 
 | 1670 |   if(a) { | 
 | 1671 |     Info = 0; | 
 | 1672 |     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info); | 
 | 1673 |     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info); | 
 | 1674 |     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info))); | 
 | 1675 |     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */ | 
 | 1676 |       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */ | 
 | 1677 |     } | 
 | 1678 |  | 
 | 1679 |     /* check if external controller listen and switch listen on or off*/ | 
 | 1680 |     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){ | 
 | 1681 |       if(a->profile.Global_Options & ON_BOARD_CODEC) { | 
 | 1682 |         dummy_plci.State = IDLE; | 
 | 1683 |         a->codec_listen[appl->Id-1] = &dummy_plci; | 
 | 1684 |         a->TelOAD[0] = (byte)(parms[3].length); | 
 | 1685 |         for(i=1;parms[3].length>=i && i<22;i++) { | 
 | 1686 |           a->TelOAD[i] = parms[3].info[i]; | 
 | 1687 |         } | 
 | 1688 |         a->TelOAD[i] = 0; | 
 | 1689 |         a->TelOSA[0] = (byte)(parms[4].length); | 
 | 1690 |         for(i=1;parms[4].length>=i && i<22;i++) { | 
 | 1691 |           a->TelOSA[i] = parms[4].info[i]; | 
 | 1692 |         } | 
 | 1693 |         a->TelOSA[i] = 0; | 
 | 1694 |       } | 
 | 1695 |       else Info = 0x2002; /* wrong controller, codec not supported */ | 
 | 1696 |     } | 
 | 1697 |     else{               /* clear listen */ | 
 | 1698 |       a->codec_listen[appl->Id-1] = (PLCI   *)0; | 
 | 1699 |     } | 
 | 1700 |   } | 
 | 1701 |   sendf(appl, | 
 | 1702 |         _LISTEN_R|CONFIRM, | 
 | 1703 |         Id, | 
 | 1704 |         Number, | 
 | 1705 |         "w",Info); | 
 | 1706 |  | 
 | 1707 |   if (a) listen_check(a); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1708 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1709 | } | 
 | 1710 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1711 | static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1712 | 		     PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1713 | { | 
 | 1714 |   word i; | 
 | 1715 |   API_PARSE * ai; | 
 | 1716 |   PLCI   * rc_plci = NULL; | 
 | 1717 |     API_PARSE ai_parms[5]; | 
 | 1718 |   word Info = 0; | 
 | 1719 |  | 
 | 1720 |   dbug(1,dprintf("info_req")); | 
 | 1721 |   for(i=0;i<5;i++) ai_parms[i].length = 0; | 
 | 1722 |  | 
 | 1723 |   ai = &msg[1]; | 
 | 1724 |  | 
 | 1725 |   if(ai->length) | 
 | 1726 |   { | 
 | 1727 |     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms)) | 
 | 1728 |     { | 
 | 1729 |       dbug(1,dprintf("AddInfo wrong")); | 
 | 1730 |       Info = _WRONG_MESSAGE_FORMAT; | 
 | 1731 |     } | 
 | 1732 |   } | 
 | 1733 |   if(!a) Info = _WRONG_STATE; | 
 | 1734 |  | 
 | 1735 |   if(!Info && plci) | 
 | 1736 |   {                /* no fac, with CPN, or KEY */ | 
 | 1737 |     rc_plci = plci; | 
 | 1738 |     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) ) | 
 | 1739 |     { | 
 | 1740 |       /* overlap sending option */ | 
 | 1741 |       dbug(1,dprintf("OvlSnd")); | 
 | 1742 |       add_s(plci,CPN,&msg[0]); | 
 | 1743 |       add_s(plci,KEY,&ai_parms[1]); | 
 | 1744 |       sig_req(plci,INFO_REQ,0); | 
 | 1745 |       send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1746 |       return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1747 |     } | 
 | 1748 |  | 
 | 1749 |     if(plci->State && ai_parms[2].length) | 
 | 1750 |     { | 
 | 1751 |       /* User_Info option */ | 
 | 1752 |       dbug(1,dprintf("UUI")); | 
 | 1753 |       add_s(plci,UUI,&ai_parms[2]); | 
 | 1754 |       sig_req(plci,USER_DATA,0); | 
 | 1755 |     } | 
 | 1756 |     else if(plci->State && ai_parms[3].length) | 
 | 1757 |     { | 
 | 1758 |       /* Facility option */ | 
 | 1759 |       dbug(1,dprintf("FAC")); | 
 | 1760 |       add_s(plci,CPN,&msg[0]); | 
 | 1761 |       add_ai(plci, &msg[1]); | 
 | 1762 |       sig_req(plci,FACILITY_REQ,0); | 
 | 1763 |     } | 
 | 1764 |     else | 
 | 1765 |     { | 
 | 1766 |       Info = _WRONG_STATE; | 
 | 1767 |     } | 
 | 1768 |   } | 
 | 1769 |   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info) | 
 | 1770 |   { | 
 | 1771 |     /* NCR_Facility option -> send UUI and Keypad too */ | 
 | 1772 |     dbug(1,dprintf("NCR_FAC")); | 
 | 1773 |     if((i=get_plci(a))) | 
 | 1774 |     { | 
 | 1775 |       rc_plci = &a->plci[i-1]; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1776 |       appl->NullCREnable  = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1777 |       rc_plci->internal_command = C_NCR_FAC_REQ; | 
 | 1778 |       rc_plci->appl = appl; | 
 | 1779 |       add_p(rc_plci,CAI,"\x01\x80"); | 
 | 1780 |       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 1781 |       sig_req(rc_plci,ASSIGN,DSIG_ID); | 
 | 1782 |       send_req(rc_plci); | 
 | 1783 |     } | 
 | 1784 |     else | 
 | 1785 |     { | 
 | 1786 |       Info = _OUT_OF_PLCI; | 
 | 1787 |     } | 
 | 1788 |  | 
 | 1789 |     if(!Info) | 
 | 1790 |     { | 
 | 1791 |       add_s(rc_plci,CPN,&msg[0]); | 
 | 1792 |       add_ai(rc_plci, &msg[1]); | 
 | 1793 |       sig_req(rc_plci,NCR_FACILITY,0); | 
 | 1794 |       send_req(rc_plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1795 |       return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1796 |      /* for application controlled supplementary services    */ | 
 | 1797 |     } | 
 | 1798 |   } | 
 | 1799 |  | 
 | 1800 |   if (!rc_plci) | 
 | 1801 |   { | 
 | 1802 |     Info = _WRONG_MESSAGE_FORMAT; | 
 | 1803 |   } | 
 | 1804 |  | 
 | 1805 |   if(!Info) | 
 | 1806 |   { | 
 | 1807 |     send_req(rc_plci); | 
 | 1808 |   } | 
 | 1809 |   else | 
 | 1810 |   {  /* appl is not assigned to a PLCI or error condition */ | 
 | 1811 |     dbug(1,dprintf("localInfoCon")); | 
 | 1812 |     sendf(appl, | 
 | 1813 |           _INFO_R|CONFIRM, | 
 | 1814 |           Id, | 
 | 1815 |           Number, | 
 | 1816 |           "w",Info); | 
 | 1817 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1818 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1819 | } | 
 | 1820 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1821 | static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1822 | 		     PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1823 | { | 
 | 1824 |   dbug(1,dprintf("info_res")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1825 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1826 | } | 
 | 1827 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1828 | static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1829 | 		      PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1830 | { | 
 | 1831 |   word Info; | 
 | 1832 |   byte ret; | 
 | 1833 |  | 
 | 1834 |   dbug(1,dprintf("alert_req")); | 
 | 1835 |  | 
 | 1836 |   Info = _WRONG_IDENTIFIER; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1837 |   ret = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1838 |   if(plci) { | 
 | 1839 |     Info = _ALERT_IGNORED; | 
 | 1840 |     if(plci->State!=INC_CON_ALERT) { | 
 | 1841 |       Info = _WRONG_STATE; | 
 | 1842 |       if(plci->State==INC_CON_PENDING) { | 
 | 1843 |         Info = 0; | 
 | 1844 |         plci->State=INC_CON_ALERT; | 
 | 1845 |         add_ai(plci, &msg[0]); | 
 | 1846 |         sig_req(plci,CALL_ALERT,0); | 
 | 1847 |         ret = 1; | 
 | 1848 |       } | 
 | 1849 |     } | 
 | 1850 |   } | 
 | 1851 |   sendf(appl, | 
 | 1852 |         _ALERT_R|CONFIRM, | 
 | 1853 |         Id, | 
 | 1854 |         Number, | 
 | 1855 |         "w",Info); | 
 | 1856 |   return ret; | 
 | 1857 | } | 
 | 1858 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 1859 | static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 1860 | 			 PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1861 | { | 
 | 1862 |   word Info = 0; | 
 | 1863 |   word i    = 0; | 
 | 1864 |  | 
 | 1865 |   word selector; | 
 | 1866 |   word SSreq; | 
 | 1867 |   long relatedPLCIvalue; | 
 | 1868 |   DIVA_CAPI_ADAPTER   * relatedadapter; | 
 | 1869 |   byte * SSparms  = ""; | 
 | 1870 |     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00"; | 
 | 1871 |     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00"; | 
 | 1872 |   API_PARSE * parms; | 
 | 1873 |     API_PARSE ss_parms[11]; | 
 | 1874 |   PLCI   *rplci; | 
 | 1875 |     byte cai[15]; | 
 | 1876 |   dword d; | 
 | 1877 |     API_PARSE dummy; | 
 | 1878 |  | 
 | 1879 |   dbug(1,dprintf("facility_req")); | 
 | 1880 |   for(i=0;i<9;i++) ss_parms[i].length = 0; | 
 | 1881 |  | 
 | 1882 |   parms = &msg[1]; | 
 | 1883 |  | 
 | 1884 |   if(!a) | 
 | 1885 |   { | 
 | 1886 |     dbug(1,dprintf("wrong Ctrl")); | 
 | 1887 |     Info = _WRONG_IDENTIFIER; | 
 | 1888 |   } | 
 | 1889 |  | 
 | 1890 |   selector = GET_WORD(msg[0].info); | 
 | 1891 |  | 
 | 1892 |   if(!Info) | 
 | 1893 |   { | 
 | 1894 |     switch(selector) | 
 | 1895 |     { | 
 | 1896 |       case SELECTOR_HANDSET: | 
 | 1897 |         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT); | 
 | 1898 |         break; | 
 | 1899 |  | 
 | 1900 |       case SELECTOR_SU_SERV: | 
 | 1901 |         if(!msg[1].length) | 
 | 1902 |         { | 
 | 1903 |           Info = _WRONG_MESSAGE_FORMAT; | 
 | 1904 |           break; | 
 | 1905 |         } | 
 | 1906 |         SSreq = GET_WORD(&(msg[1].info[1])); | 
 | 1907 |         PUT_WORD(&RCparms[1],SSreq); | 
 | 1908 |         SSparms = RCparms; | 
 | 1909 |         switch(SSreq) | 
 | 1910 |         { | 
 | 1911 |           case S_GET_SUPPORTED_SERVICES: | 
 | 1912 |             if((i=get_plci(a))) | 
 | 1913 |             { | 
 | 1914 |               rplci = &a->plci[i-1]; | 
 | 1915 |               rplci->appl = appl; | 
 | 1916 |               add_p(rplci,CAI,"\x01\x80"); | 
 | 1917 |               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 1918 |               sig_req(rplci,ASSIGN,DSIG_ID); | 
 | 1919 |               send_req(rplci); | 
 | 1920 |             } | 
 | 1921 |             else | 
 | 1922 |             { | 
 | 1923 |               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); | 
 | 1924 |               SSparms = (byte *)SSstruct; | 
 | 1925 |               break; | 
 | 1926 |             } | 
 | 1927 |             rplci->internal_command = GETSERV_REQ_PEND; | 
 | 1928 |             rplci->number = Number; | 
 | 1929 |             rplci->appl = appl; | 
 | 1930 |             sig_req(rplci,S_SUPPORTED,0); | 
 | 1931 |             send_req(rplci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1932 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1933 |             break; | 
 | 1934 |  | 
 | 1935 |           case S_LISTEN: | 
 | 1936 |             if(parms->length==7) | 
 | 1937 |             { | 
 | 1938 |               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | 
 | 1939 |               { | 
 | 1940 |                 dbug(1,dprintf("format wrong")); | 
 | 1941 |                 Info = _WRONG_MESSAGE_FORMAT; | 
 | 1942 |                 break; | 
 | 1943 |               } | 
 | 1944 |             } | 
 | 1945 |             else | 
 | 1946 |             { | 
 | 1947 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 1948 |               break; | 
 | 1949 |             } | 
 | 1950 |             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info); | 
 | 1951 |             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */ | 
 | 1952 |             { | 
 | 1953 |               if((i=get_plci(a))) | 
 | 1954 |               { | 
 | 1955 |                 rplci = &a->plci[i-1]; | 
 | 1956 |                 rplci->appl = appl; | 
 | 1957 |                 add_p(rplci,CAI,"\x01\x80"); | 
 | 1958 |                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 1959 |                 sig_req(rplci,ASSIGN,DSIG_ID); | 
 | 1960 |                 send_req(rplci); | 
 | 1961 |               } | 
 | 1962 |               else | 
 | 1963 |               { | 
 | 1964 |                 break; | 
 | 1965 |               } | 
 | 1966 |               rplci->internal_command = GET_MWI_STATE; | 
 | 1967 |               rplci->number = Number; | 
 | 1968 |               sig_req(rplci,MWI_POLL,0); | 
 | 1969 |               send_req(rplci); | 
 | 1970 |             } | 
 | 1971 |             break; | 
 | 1972 |  | 
 | 1973 |           case S_HOLD: | 
 | 1974 |             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms); | 
 | 1975 |             if(plci && plci->State && plci->SuppState==IDLE) | 
 | 1976 |             { | 
 | 1977 |               plci->SuppState = HOLD_REQUEST; | 
 | 1978 |               plci->command = C_HOLD_REQ; | 
 | 1979 |               add_s(plci,CAI,&ss_parms[1]); | 
 | 1980 |               sig_req(plci,CALL_HOLD,0); | 
 | 1981 |               send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 1982 |               return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1983 |             } | 
 | 1984 |             else Info = 0x3010;                    /* wrong state           */ | 
 | 1985 |             break; | 
 | 1986 |           case S_RETRIEVE: | 
 | 1987 |             if(plci && plci->State && plci->SuppState==CALL_HELD) | 
 | 1988 |             { | 
 | 1989 |               if(Id & EXT_CONTROLLER) | 
 | 1990 |               { | 
 | 1991 |                 if(AdvCodecSupport(a, plci, appl, 0)) | 
 | 1992 |                 { | 
 | 1993 |                   Info = 0x3010;                    /* wrong state           */ | 
 | 1994 |                   break; | 
 | 1995 |                 } | 
 | 1996 |               } | 
 | 1997 |               else plci->tel = 0; | 
 | 1998 |  | 
 | 1999 |               plci->SuppState = RETRIEVE_REQUEST; | 
 | 2000 |               plci->command = C_RETRIEVE_REQ; | 
 | 2001 |               if(plci->spoofed_msg==SPOOFING_REQUIRED) | 
 | 2002 |               { | 
 | 2003 |                 plci->spoofed_msg = CALL_RETRIEVE; | 
 | 2004 |                 plci->internal_command = BLOCK_PLCI; | 
 | 2005 |                 plci->command = 0; | 
 | 2006 |                 dbug(1,dprintf("Spoof")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2007 |                 return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2008 |               } | 
 | 2009 |               else | 
 | 2010 |               { | 
 | 2011 |                 sig_req(plci,CALL_RETRIEVE,0); | 
 | 2012 |                 send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2013 |                 return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2014 |               } | 
 | 2015 |             } | 
 | 2016 |             else Info = 0x3010;                    /* wrong state           */ | 
 | 2017 |             break; | 
 | 2018 |           case S_SUSPEND: | 
 | 2019 |             if(parms->length) | 
 | 2020 |             { | 
 | 2021 |               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms)) | 
 | 2022 |               { | 
 | 2023 |                 dbug(1,dprintf("format wrong")); | 
 | 2024 |                 Info = _WRONG_MESSAGE_FORMAT; | 
 | 2025 |                 break; | 
 | 2026 |               } | 
 | 2027 |             } | 
 | 2028 |             if(plci && plci->State) | 
 | 2029 |             { | 
 | 2030 |               add_s(plci,CAI,&ss_parms[2]); | 
 | 2031 |               plci->command = SUSPEND_REQ; | 
 | 2032 |               sig_req(plci,SUSPEND,0); | 
 | 2033 |               plci->State = SUSPENDING; | 
 | 2034 |               send_req(plci); | 
 | 2035 |             } | 
 | 2036 |             else Info = 0x3010;                    /* wrong state           */ | 
 | 2037 |             break; | 
 | 2038 |  | 
 | 2039 |           case S_RESUME: | 
 | 2040 |             if(!(i=get_plci(a)) ) | 
 | 2041 |             { | 
 | 2042 |               Info = _OUT_OF_PLCI; | 
 | 2043 |               break; | 
 | 2044 |             } | 
 | 2045 |             rplci = &a->plci[i-1]; | 
 | 2046 |             rplci->appl = appl; | 
 | 2047 |             rplci->number = Number; | 
 | 2048 |             rplci->tel = 0; | 
 | 2049 |             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | 
 | 2050 |             /* check 'external controller' bit for codec support */ | 
 | 2051 |             if(Id & EXT_CONTROLLER) | 
 | 2052 |             { | 
 | 2053 |               if(AdvCodecSupport(a, rplci, appl, 0) ) | 
 | 2054 |               { | 
 | 2055 |                 rplci->Id = 0; | 
 | 2056 |                 Info = 0x300A; | 
 | 2057 |                 break; | 
 | 2058 |               } | 
 | 2059 |             } | 
 | 2060 |             if(parms->length) | 
 | 2061 |             { | 
 | 2062 |               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms)) | 
 | 2063 |               { | 
 | 2064 |                 dbug(1,dprintf("format wrong")); | 
 | 2065 |                 rplci->Id = 0; | 
 | 2066 |                 Info = _WRONG_MESSAGE_FORMAT; | 
 | 2067 |                 break; | 
 | 2068 |               } | 
 | 2069 |             } | 
 | 2070 |             dummy.length = 0; | 
 | 2071 |             dummy.info = "\x00"; | 
 | 2072 |             add_b1(rplci, &dummy, 0, 0); | 
 | 2073 |             if (a->Info_Mask[appl->Id-1] & 0x200) | 
 | 2074 |             { | 
 | 2075 |               /* early B3 connect (CIP mask bit 9) no release after a disc */ | 
 | 2076 |               add_p(rplci,LLI,"\x01\x01"); | 
 | 2077 |             } | 
 | 2078 |             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 2079 |             sig_req(rplci,ASSIGN,DSIG_ID); | 
 | 2080 |             send_req(rplci); | 
 | 2081 |             add_s(rplci,CAI,&ss_parms[2]); | 
 | 2082 |             rplci->command = RESUME_REQ; | 
 | 2083 |             sig_req(rplci,RESUME,0); | 
 | 2084 |             rplci->State = RESUMING; | 
 | 2085 |             send_req(rplci); | 
 | 2086 |             break; | 
 | 2087 |  | 
 | 2088 |           case S_CONF_BEGIN: /* Request */ | 
 | 2089 |           case S_CONF_DROP: | 
 | 2090 |           case S_CONF_ISOLATE: | 
 | 2091 |           case S_CONF_REATTACH: | 
 | 2092 |             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | 
 | 2093 |             { | 
 | 2094 |               dbug(1,dprintf("format wrong")); | 
 | 2095 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2096 |               break; | 
 | 2097 |             } | 
 | 2098 |             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD))) | 
 | 2099 |             { | 
 | 2100 |               d = GET_DWORD(ss_parms[2].info);      | 
 | 2101 |               if(d>=0x80) | 
 | 2102 |               { | 
 | 2103 |                 dbug(1,dprintf("format wrong")); | 
 | 2104 |                 Info = _WRONG_MESSAGE_FORMAT; | 
 | 2105 |                 break; | 
 | 2106 |               } | 
 | 2107 |               plci->ptyState = (byte)SSreq; | 
 | 2108 |               plci->command = 0; | 
 | 2109 |               cai[0] = 2; | 
 | 2110 |               switch(SSreq) | 
 | 2111 |               { | 
 | 2112 |               case S_CONF_BEGIN: | 
 | 2113 |                   cai[1] = CONF_BEGIN; | 
 | 2114 |                   plci->internal_command = CONF_BEGIN_REQ_PEND; | 
 | 2115 |                   break; | 
 | 2116 |               case S_CONF_DROP: | 
 | 2117 |                   cai[1] = CONF_DROP; | 
 | 2118 |                   plci->internal_command = CONF_DROP_REQ_PEND; | 
 | 2119 |                   break; | 
 | 2120 |               case S_CONF_ISOLATE: | 
 | 2121 |                   cai[1] = CONF_ISOLATE; | 
 | 2122 |                   plci->internal_command = CONF_ISOLATE_REQ_PEND; | 
 | 2123 |                   break; | 
 | 2124 |               case S_CONF_REATTACH: | 
 | 2125 |                   cai[1] = CONF_REATTACH; | 
 | 2126 |                   plci->internal_command = CONF_REATTACH_REQ_PEND; | 
 | 2127 |                   break; | 
 | 2128 |               } | 
 | 2129 |               cai[2] = (byte)d; /* Conference Size resp. PartyId */ | 
 | 2130 |               add_p(plci,CAI,cai); | 
 | 2131 |               sig_req(plci,S_SERVICE,0); | 
 | 2132 |               send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2133 |               return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2134 |             } | 
 | 2135 |             else Info = 0x3010;                    /* wrong state           */ | 
 | 2136 |             break; | 
 | 2137 |  | 
 | 2138 |           case S_ECT: | 
 | 2139 |           case S_3PTY_BEGIN: | 
 | 2140 |           case S_3PTY_END: | 
 | 2141 |           case S_CONF_ADD: | 
 | 2142 |             if(parms->length==7) | 
 | 2143 |             { | 
 | 2144 |               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | 
 | 2145 |               { | 
 | 2146 |                 dbug(1,dprintf("format wrong")); | 
 | 2147 |                 Info = _WRONG_MESSAGE_FORMAT; | 
 | 2148 |                 break; | 
 | 2149 |               } | 
 | 2150 |             } | 
 | 2151 |             else if(parms->length==8) /* workaround for the T-View-S */ | 
 | 2152 |             { | 
 | 2153 |               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms)) | 
 | 2154 |               { | 
 | 2155 |                 dbug(1,dprintf("format wrong")); | 
 | 2156 |                 Info = _WRONG_MESSAGE_FORMAT; | 
 | 2157 |                 break; | 
 | 2158 |               } | 
 | 2159 |             } | 
 | 2160 |             else | 
 | 2161 |             { | 
 | 2162 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2163 |               break; | 
 | 2164 |             } | 
 | 2165 |             if(!msg[1].length) | 
 | 2166 |             { | 
 | 2167 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2168 |               break; | 
 | 2169 |             } | 
 | 2170 |             if (!plci) | 
 | 2171 |             { | 
 | 2172 |               Info = _WRONG_IDENTIFIER; | 
 | 2173 |               break; | 
 | 2174 |             } | 
 | 2175 |             relatedPLCIvalue = GET_DWORD(ss_parms[2].info); | 
 | 2176 |             relatedPLCIvalue &= 0x0000FFFF; | 
 | 2177 |             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue)); | 
 | 2178 |             /* controller starts with 0 up to (max_adapter - 1) */ | 
 | 2179 |             if (((relatedPLCIvalue & 0x7f) == 0) | 
 | 2180 |              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0) | 
 | 2181 |              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter)) | 
 | 2182 |             { | 
 | 2183 |               if(SSreq==S_3PTY_END) | 
 | 2184 |               { | 
 | 2185 |                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI")); | 
 | 2186 |                 rplci = plci; | 
 | 2187 |               } | 
 | 2188 |               else | 
 | 2189 |               { | 
 | 2190 |                 Info = 0x3010;                    /* wrong state           */ | 
 | 2191 |                 break; | 
 | 2192 |               } | 
 | 2193 |             } | 
 | 2194 |             else | 
 | 2195 |             {   | 
 | 2196 |               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1]; | 
 | 2197 |               relatedPLCIvalue >>=8; | 
 | 2198 |               /* find PLCI PTR*/ | 
 | 2199 |               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++) | 
 | 2200 |               { | 
 | 2201 |                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue) | 
 | 2202 |                 { | 
 | 2203 |                   rplci = &relatedadapter->plci[i]; | 
 | 2204 |                 } | 
 | 2205 |               } | 
 | 2206 |               if(!rplci || !relatedPLCIvalue) | 
 | 2207 |               { | 
 | 2208 |                 if(SSreq==S_3PTY_END) | 
 | 2209 |                 { | 
 | 2210 |                   dbug(1, dprintf("use 2nd PLCI=PLCI")); | 
 | 2211 |                   rplci = plci; | 
 | 2212 |                 } | 
 | 2213 |                 else | 
 | 2214 |                 { | 
 | 2215 |                   Info = 0x3010;                    /* wrong state           */ | 
 | 2216 |                   break; | 
 | 2217 |                 } | 
 | 2218 |               } | 
 | 2219 |             } | 
 | 2220 | /* | 
 | 2221 |             dbug(1,dprintf("rplci:%x",rplci)); | 
 | 2222 |             dbug(1,dprintf("plci:%x",plci)); | 
 | 2223 |             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState)); | 
 | 2224 |             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState)); | 
 | 2225 |             dbug(1,dprintf("SSreq:%x",SSreq)); | 
 | 2226 |             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command)); | 
 | 2227 |             dbug(1,dprintf("rplci->appl:%x",rplci->appl)); | 
 | 2228 |             dbug(1,dprintf("rplci->Id:%x",rplci->Id)); | 
 | 2229 | */ | 
 | 2230 |             /* send PTY/ECT req, cannot check all states because of US stuff */ | 
 | 2231 |             if( !rplci->internal_command && rplci->appl ) | 
 | 2232 |             { | 
 | 2233 |               plci->command = 0; | 
 | 2234 |               rplci->relatedPTYPLCI = plci; | 
 | 2235 |               plci->relatedPTYPLCI = rplci; | 
 | 2236 |               rplci->ptyState = (byte)SSreq; | 
 | 2237 |               if(SSreq==S_ECT) | 
 | 2238 |               { | 
 | 2239 |                 rplci->internal_command = ECT_REQ_PEND; | 
 | 2240 |                 cai[1] = ECT_EXECUTE; | 
 | 2241 |  | 
 | 2242 |                 rplci->vswitchstate=0; | 
 | 2243 |                 rplci->vsprot=0; | 
 | 2244 |                 rplci->vsprotdialect=0; | 
 | 2245 |                 plci->vswitchstate=0; | 
 | 2246 |                 plci->vsprot=0; | 
 | 2247 |                 plci->vsprotdialect=0; | 
 | 2248 |  | 
 | 2249 |               } | 
 | 2250 |               else if(SSreq==S_CONF_ADD) | 
 | 2251 |               { | 
 | 2252 |                 rplci->internal_command = CONF_ADD_REQ_PEND; | 
 | 2253 |                 cai[1] = CONF_ADD; | 
 | 2254 |               } | 
 | 2255 |               else | 
 | 2256 |               { | 
 | 2257 |                 rplci->internal_command = PTY_REQ_PEND; | 
 | 2258 |                 cai[1] = (byte)(SSreq-3); | 
 | 2259 |               } | 
 | 2260 |               rplci->number = Number; | 
 | 2261 |               if(plci!=rplci) /* explicit invocation */ | 
 | 2262 |               { | 
 | 2263 |                 cai[0] = 2; | 
 | 2264 |                 cai[2] = plci->Sig.Id; | 
 | 2265 |                 dbug(1,dprintf("explicit invocation")); | 
 | 2266 |               } | 
 | 2267 |               else | 
 | 2268 |               { | 
 | 2269 |                 dbug(1,dprintf("implicit invocation")); | 
 | 2270 |                 cai[0] = 1; | 
 | 2271 |               } | 
 | 2272 |               add_p(rplci,CAI,cai); | 
 | 2273 |               sig_req(rplci,S_SERVICE,0); | 
 | 2274 |               send_req(rplci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2275 |               return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2276 |             } | 
 | 2277 |             else | 
 | 2278 |             { | 
 | 2279 |               dbug(0,dprintf("Wrong line")); | 
 | 2280 |               Info = 0x3010;                    /* wrong state           */ | 
 | 2281 |               break; | 
 | 2282 |             } | 
 | 2283 |             break; | 
 | 2284 |  | 
 | 2285 |           case S_CALL_DEFLECTION: | 
 | 2286 |             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms)) | 
 | 2287 |             { | 
 | 2288 |               dbug(1,dprintf("format wrong")); | 
 | 2289 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2290 |               break; | 
 | 2291 |             } | 
 | 2292 |             if (!plci) | 
 | 2293 |             { | 
 | 2294 |               Info = _WRONG_IDENTIFIER; | 
 | 2295 |               break; | 
 | 2296 |             } | 
 | 2297 |             /* reuse unused screening indicator */ | 
 | 2298 |             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0])); | 
 | 2299 |             plci->command = 0; | 
 | 2300 |             plci->internal_command = CD_REQ_PEND; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2301 |             appl->CDEnable = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2302 |             cai[0] = 1; | 
 | 2303 |             cai[1] = CALL_DEFLECTION; | 
 | 2304 |             add_p(plci,CAI,cai); | 
 | 2305 |             add_p(plci,CPN,ss_parms[3].info); | 
 | 2306 |             sig_req(plci,S_SERVICE,0); | 
 | 2307 |             send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2308 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2309 |             break; | 
 | 2310 |  | 
 | 2311 |           case S_CALL_FORWARDING_START: | 
 | 2312 |             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms)) | 
 | 2313 |             { | 
 | 2314 |               dbug(1,dprintf("format wrong")); | 
 | 2315 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2316 |               break; | 
 | 2317 |             } | 
 | 2318 |  | 
 | 2319 |             if((i=get_plci(a))) | 
 | 2320 |             { | 
 | 2321 |               rplci = &a->plci[i-1]; | 
 | 2322 |               rplci->appl = appl; | 
 | 2323 |               add_p(rplci,CAI,"\x01\x80"); | 
 | 2324 |               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 2325 |               sig_req(rplci,ASSIGN,DSIG_ID); | 
 | 2326 |               send_req(rplci); | 
 | 2327 |             } | 
 | 2328 |             else | 
 | 2329 |             { | 
 | 2330 |               Info = _OUT_OF_PLCI; | 
 | 2331 |               break; | 
 | 2332 |             } | 
 | 2333 |  | 
 | 2334 |             /* reuse unused screening indicator */ | 
 | 2335 |             rplci->internal_command = CF_START_PEND; | 
 | 2336 |             rplci->appl = appl; | 
 | 2337 |             rplci->number = Number; | 
 | 2338 |             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0])); | 
 | 2339 |             cai[0] = 2; | 
 | 2340 |             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ | 
 | 2341 |             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */ | 
 | 2342 |             add_p(rplci,CAI,cai); | 
 | 2343 |             add_p(rplci,OAD,ss_parms[5].info); | 
 | 2344 |             add_p(rplci,CPN,ss_parms[6].info); | 
 | 2345 |             sig_req(rplci,S_SERVICE,0); | 
 | 2346 |             send_req(rplci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2347 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2348 |             break; | 
 | 2349 |  | 
 | 2350 |           case S_INTERROGATE_DIVERSION: | 
 | 2351 |           case S_INTERROGATE_NUMBERS: | 
 | 2352 |           case S_CALL_FORWARDING_STOP: | 
 | 2353 |           case S_CCBS_REQUEST: | 
 | 2354 |           case S_CCBS_DEACTIVATE: | 
 | 2355 |           case S_CCBS_INTERROGATE: | 
 | 2356 |             switch(SSreq) | 
 | 2357 |             { | 
 | 2358 |             case S_INTERROGATE_NUMBERS: | 
 | 2359 |                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | 
 | 2360 |                 { | 
 | 2361 |                   dbug(0,dprintf("format wrong")); | 
 | 2362 |                   Info = _WRONG_MESSAGE_FORMAT; | 
 | 2363 |                 } | 
 | 2364 |                 break; | 
 | 2365 |             case S_CCBS_REQUEST: | 
 | 2366 |             case S_CCBS_DEACTIVATE: | 
 | 2367 |                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms)) | 
 | 2368 |                 { | 
 | 2369 |                   dbug(0,dprintf("format wrong")); | 
 | 2370 |                   Info = _WRONG_MESSAGE_FORMAT; | 
 | 2371 |                 } | 
 | 2372 |                 break; | 
 | 2373 |             case S_CCBS_INTERROGATE: | 
 | 2374 |                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms)) | 
 | 2375 |                 { | 
 | 2376 |                   dbug(0,dprintf("format wrong")); | 
 | 2377 |                   Info = _WRONG_MESSAGE_FORMAT; | 
 | 2378 |                 } | 
 | 2379 |                 break; | 
 | 2380 |             default: | 
 | 2381 |             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms)) | 
 | 2382 |             { | 
 | 2383 |               dbug(0,dprintf("format wrong")); | 
 | 2384 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2385 |               break; | 
 | 2386 |             } | 
 | 2387 |                 break; | 
 | 2388 |             } | 
 | 2389 |  | 
 | 2390 |             if(Info) break; | 
 | 2391 |             if((i=get_plci(a))) | 
 | 2392 |             { | 
 | 2393 |               rplci = &a->plci[i-1]; | 
 | 2394 |               switch(SSreq) | 
 | 2395 |               { | 
 | 2396 |                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */ | 
 | 2397 |                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ | 
 | 2398 |                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */ | 
 | 2399 |                   break; | 
 | 2400 |                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */ | 
 | 2401 |                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */ | 
 | 2402 |                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */ | 
 | 2403 |                   break; | 
 | 2404 |                 case S_CALL_FORWARDING_STOP: | 
 | 2405 |                   rplci->internal_command = CF_STOP_PEND; | 
 | 2406 |                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ | 
 | 2407 |                   break; | 
 | 2408 |                 case S_CCBS_REQUEST: | 
 | 2409 |                   cai[1] = CCBS_REQUEST; | 
 | 2410 |                   rplci->internal_command = CCBS_REQUEST_REQ_PEND; | 
 | 2411 |                   break; | 
 | 2412 |                 case S_CCBS_DEACTIVATE: | 
 | 2413 |                   cai[1] = CCBS_DEACTIVATE; | 
 | 2414 |                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND; | 
 | 2415 |                   break; | 
 | 2416 |                 case S_CCBS_INTERROGATE: | 
 | 2417 |                   cai[1] = CCBS_INTERROGATE; | 
 | 2418 |                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND; | 
 | 2419 |                   break; | 
 | 2420 |                 default: | 
 | 2421 |                   cai[1] = 0; | 
 | 2422 |                 break; | 
 | 2423 |               } | 
 | 2424 |               rplci->appl = appl; | 
 | 2425 |               rplci->number = Number; | 
 | 2426 |               add_p(rplci,CAI,"\x01\x80"); | 
 | 2427 |               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 2428 |               sig_req(rplci,ASSIGN,DSIG_ID); | 
 | 2429 |               send_req(rplci); | 
 | 2430 |             } | 
 | 2431 |             else | 
 | 2432 |             { | 
 | 2433 |               Info = _OUT_OF_PLCI; | 
 | 2434 |               break; | 
 | 2435 |             } | 
 | 2436 |  | 
 | 2437 |             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0])); | 
 | 2438 |             switch(SSreq) | 
 | 2439 |             { | 
 | 2440 |             case S_INTERROGATE_NUMBERS: | 
 | 2441 |                 cai[0] = 1; | 
 | 2442 |                 add_p(rplci,CAI,cai); | 
 | 2443 |                 break; | 
 | 2444 |             case S_CCBS_REQUEST: | 
 | 2445 |             case S_CCBS_DEACTIVATE: | 
 | 2446 |                 cai[0] = 3; | 
 | 2447 |                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0]))); | 
 | 2448 |                 add_p(rplci,CAI,cai); | 
 | 2449 |                 break; | 
 | 2450 |             case S_CCBS_INTERROGATE: | 
 | 2451 |                 cai[0] = 3; | 
 | 2452 |                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0]))); | 
 | 2453 |                 add_p(rplci,CAI,cai); | 
 | 2454 |                 add_p(rplci,OAD,ss_parms[4].info); | 
 | 2455 |                 break; | 
 | 2456 |             default: | 
 | 2457 |             cai[0] = 2; | 
 | 2458 |             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */ | 
 | 2459 |             add_p(rplci,CAI,cai); | 
 | 2460 |             add_p(rplci,OAD,ss_parms[5].info); | 
 | 2461 |                 break; | 
 | 2462 |             } | 
 | 2463 |                          | 
 | 2464 |             sig_req(rplci,S_SERVICE,0); | 
 | 2465 |             send_req(rplci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2466 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2467 |             break; | 
 | 2468 |  | 
 | 2469 |           case S_MWI_ACTIVATE: | 
 | 2470 |             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms)) | 
 | 2471 |             { | 
 | 2472 |               dbug(1,dprintf("format wrong")); | 
 | 2473 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2474 |               break; | 
 | 2475 |             } | 
 | 2476 |             if(!plci) | 
 | 2477 |             {                                | 
 | 2478 |               if((i=get_plci(a))) | 
 | 2479 |               { | 
 | 2480 |                 rplci = &a->plci[i-1]; | 
 | 2481 |                 rplci->appl = appl; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2482 |                 rplci->cr_enquiry=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2483 |                 add_p(rplci,CAI,"\x01\x80"); | 
 | 2484 |                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 2485 |                 sig_req(rplci,ASSIGN,DSIG_ID); | 
 | 2486 |                 send_req(rplci); | 
 | 2487 |               } | 
 | 2488 |               else | 
 | 2489 |               { | 
 | 2490 |                 Info = _OUT_OF_PLCI; | 
 | 2491 |                 break; | 
 | 2492 |               } | 
 | 2493 |             } | 
 | 2494 |             else | 
 | 2495 |             { | 
 | 2496 |               rplci = plci; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2497 |               rplci->cr_enquiry=false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2498 |             } | 
 | 2499 |  | 
 | 2500 |             rplci->command = 0; | 
 | 2501 |             rplci->internal_command = MWI_ACTIVATE_REQ_PEND; | 
 | 2502 |             rplci->appl = appl; | 
 | 2503 |             rplci->number = Number; | 
 | 2504 |  | 
 | 2505 |             cai[0] = 13; | 
 | 2506 |             cai[1] = ACTIVATION_MWI; /* Function */ | 
 | 2507 |             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ | 
 | 2508 |             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */ | 
 | 2509 |             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */ | 
 | 2510 |             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */ | 
 | 2511 |             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */ | 
 | 2512 |             add_p(rplci,CAI,cai); | 
 | 2513 |             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */ | 
 | 2514 |             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */ | 
 | 2515 |             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */ | 
 | 2516 |             add_p(rplci,UID,ss_parms[10].info); /* Time */ | 
 | 2517 |             sig_req(rplci,S_SERVICE,0); | 
 | 2518 |             send_req(rplci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2519 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2520 |  | 
 | 2521 |           case S_MWI_DEACTIVATE: | 
 | 2522 |             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms)) | 
 | 2523 |             { | 
 | 2524 |               dbug(1,dprintf("format wrong")); | 
 | 2525 |               Info = _WRONG_MESSAGE_FORMAT; | 
 | 2526 |               break; | 
 | 2527 |             } | 
 | 2528 |             if(!plci) | 
 | 2529 |             {                                | 
 | 2530 |               if((i=get_plci(a))) | 
 | 2531 |               { | 
 | 2532 |                 rplci = &a->plci[i-1]; | 
 | 2533 |                 rplci->appl = appl; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2534 |                 rplci->cr_enquiry=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2535 |                 add_p(rplci,CAI,"\x01\x80"); | 
 | 2536 |                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 2537 |                 sig_req(rplci,ASSIGN,DSIG_ID); | 
 | 2538 |                 send_req(rplci); | 
 | 2539 |               } | 
 | 2540 |               else | 
 | 2541 |               { | 
 | 2542 |                 Info = _OUT_OF_PLCI; | 
 | 2543 |                 break; | 
 | 2544 |               } | 
 | 2545 |             } | 
 | 2546 |             else | 
 | 2547 |             { | 
 | 2548 |               rplci = plci; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2549 |               rplci->cr_enquiry=false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2550 |             } | 
 | 2551 |  | 
 | 2552 |             rplci->command = 0; | 
 | 2553 |             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND; | 
 | 2554 |             rplci->appl = appl; | 
 | 2555 |             rplci->number = Number; | 
 | 2556 |  | 
 | 2557 |             cai[0] = 5; | 
 | 2558 |             cai[1] = DEACTIVATION_MWI; /* Function */ | 
 | 2559 |             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ | 
 | 2560 |             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */ | 
 | 2561 |             add_p(rplci,CAI,cai); | 
 | 2562 |             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */ | 
 | 2563 |             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */ | 
 | 2564 |             sig_req(rplci,S_SERVICE,0); | 
 | 2565 |             send_req(rplci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2566 |             return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2567 |  | 
 | 2568 |           default: | 
 | 2569 |             Info = 0x300E;  /* not supported */ | 
 | 2570 |             break; | 
 | 2571 |         } | 
 | 2572 |         break; /* case SELECTOR_SU_SERV: end */ | 
 | 2573 |  | 
 | 2574 |  | 
 | 2575 |       case SELECTOR_DTMF: | 
 | 2576 |         return (dtmf_request (Id, Number, a, plci, appl, msg)); | 
 | 2577 |  | 
 | 2578 |  | 
 | 2579 |  | 
 | 2580 |       case SELECTOR_LINE_INTERCONNECT: | 
 | 2581 |         return (mixer_request (Id, Number, a, plci, appl, msg)); | 
 | 2582 |  | 
 | 2583 |  | 
 | 2584 |  | 
 | 2585 |       case PRIV_SELECTOR_ECHO_CANCELLER: | 
 | 2586 |         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC; | 
 | 2587 |         return (ec_request (Id, Number, a, plci, appl, msg)); | 
 | 2588 |  | 
 | 2589 |       case SELECTOR_ECHO_CANCELLER: | 
 | 2590 |         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC; | 
 | 2591 |         return (ec_request (Id, Number, a, plci, appl, msg)); | 
 | 2592 |  | 
 | 2593 |  | 
 | 2594 |       case SELECTOR_V42BIS: | 
 | 2595 |       default: | 
 | 2596 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 2597 |         break; | 
 | 2598 |     } /* end of switch(selector) */ | 
 | 2599 |   } | 
 | 2600 |  | 
 | 2601 |   dbug(1,dprintf("SendFacRc")); | 
 | 2602 |   sendf(appl, | 
 | 2603 |         _FACILITY_R|CONFIRM, | 
 | 2604 |         Id, | 
 | 2605 |         Number, | 
 | 2606 |         "wws",Info,selector,SSparms); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2607 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2608 | } | 
 | 2609 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 2610 | static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 2611 | 			 PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2612 | { | 
 | 2613 |   dbug(1,dprintf("facility_res")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2614 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2615 | } | 
 | 2616 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 2617 | static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 2618 | 			   PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2619 | { | 
 | 2620 |   word Info = 0; | 
 | 2621 |   byte req; | 
 | 2622 |   byte len; | 
 | 2623 |   word w; | 
 | 2624 |   word fax_control_bits, fax_feature_bits, fax_info_change; | 
 | 2625 |   API_PARSE * ncpi; | 
 | 2626 |     byte pvc[2]; | 
 | 2627 |  | 
 | 2628 |     API_PARSE fax_parms[9]; | 
 | 2629 |   word i; | 
 | 2630 |  | 
 | 2631 |  | 
 | 2632 |   dbug(1,dprintf("connect_b3_req")); | 
 | 2633 |   if(plci) | 
 | 2634 |   { | 
 | 2635 |     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) | 
 | 2636 |      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE)) | 
 | 2637 |     { | 
 | 2638 |       Info = _WRONG_STATE; | 
 | 2639 |     } | 
 | 2640 |     else | 
 | 2641 |     { | 
 | 2642 |       /* local reply if assign unsuccessfull | 
 | 2643 |          or B3 protocol allows only one layer 3 connection | 
 | 2644 |            and already connected | 
 | 2645 |              or B2 protocol not any LAPD | 
 | 2646 |                and connect_b3_req contradicts originate/answer direction */ | 
 | 2647 |       if (!plci->NL.Id | 
 | 2648 |        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)) | 
 | 2649 |         && ((plci->channels != 0) | 
 | 2650 |          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)) | 
 | 2651 |           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL)))))) | 
 | 2652 |       { | 
 | 2653 |         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x", | 
 | 2654 |                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState)); | 
 | 2655 |         Info = _WRONG_STATE; | 
 | 2656 |         sendf(appl,                                                         | 
 | 2657 |               _CONNECT_B3_R|CONFIRM, | 
 | 2658 |               Id, | 
 | 2659 |               Number, | 
 | 2660 |               "w",Info); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2661 |         return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2662 |       } | 
 | 2663 |       plci->requested_options_conn = 0; | 
 | 2664 |  | 
 | 2665 |       req = N_CONNECT; | 
 | 2666 |       ncpi = &parms[0]; | 
 | 2667 |       if(plci->B3_prot==2 || plci->B3_prot==3) | 
 | 2668 |       { | 
 | 2669 |         if(ncpi->length>2) | 
 | 2670 |         { | 
 | 2671 |           /* check for PVC */ | 
 | 2672 |           if(ncpi->info[2] || ncpi->info[3]) | 
 | 2673 |           { | 
 | 2674 |             pvc[0] = ncpi->info[3]; | 
 | 2675 |             pvc[1] = ncpi->info[2]; | 
 | 2676 |             add_d(plci,2,pvc); | 
 | 2677 |             req = N_RESET; | 
 | 2678 |           } | 
 | 2679 |           else | 
 | 2680 |           { | 
 | 2681 |             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT; | 
 | 2682 |             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]); | 
 | 2683 |           } | 
 | 2684 |         } | 
 | 2685 |       } | 
 | 2686 |       else if(plci->B3_prot==5) | 
 | 2687 |       { | 
 | 2688 |         if (plci->NL.Id && !plci->nl_remove_id) | 
 | 2689 |         { | 
 | 2690 |           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low); | 
 | 2691 |           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low); | 
 | 2692 |           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS) | 
 | 2693 |            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)) | 
 | 2694 |           { | 
| Jiri Slaby | 1ea7084 | 2009-11-04 08:28:12 -0800 | [diff] [blame] | 2695 |             len = offsetof(T30_INFO, universal_6); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2696 |             fax_info_change = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2697 |             if (ncpi->length >= 4) | 
 | 2698 |             { | 
 | 2699 |               w = GET_WORD(&ncpi->info[3]); | 
 | 2700 |               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001))) | 
 | 2701 |               { | 
 | 2702 |                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution = | 
 | 2703 |                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) | | 
 | 2704 |                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0)); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2705 |                 fax_info_change = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2706 |               } | 
 | 2707 |               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS); | 
 | 2708 |               if (w & 0x0002)  /* Fax-polling request */ | 
 | 2709 |                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING; | 
 | 2710 |               if ((w & 0x0004) /* Request to send / poll another document */ | 
 | 2711 |                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS)) | 
 | 2712 |               { | 
 | 2713 |                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS; | 
 | 2714 |               } | 
 | 2715 |               if (ncpi->length >= 6) | 
 | 2716 |               { | 
 | 2717 |                 w = GET_WORD(&ncpi->info[5]); | 
 | 2718 |                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format) | 
 | 2719 |                 { | 
 | 2720 |                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2721 |                   fax_info_change = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2722 |                 } | 
 | 2723 |  | 
 | 2724 |                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | 
 | 2725 |                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */ | 
 | 2726 |                 { | 
 | 2727 |                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD); | 
 | 2728 |                 } | 
 | 2729 |                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD)) | 
 | 2730 |                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */ | 
 | 2731 |                 { | 
 | 2732 |                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD); | 
 | 2733 |                 } | 
 | 2734 |                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING | | 
 | 2735 |                   T30_CONTROL_BIT_ACCEPT_PASSWORD); | 
 | 2736 |                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1]) | 
 | 2737 |                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | 
 | 2738 |                 { | 
 | 2739 |                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms)) | 
 | 2740 |                     Info = _WRONG_MESSAGE_FORMAT; | 
 | 2741 |                   else | 
 | 2742 |                   { | 
 | 2743 |                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1]) | 
 | 2744 |                       & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | 
 | 2745 |       { | 
 | 2746 |                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD; | 
 | 2747 |                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING) | 
 | 2748 |                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; | 
 | 2749 |       } | 
 | 2750 |                     w = fax_parms[4].length; | 
 | 2751 |                     if (w > 20) | 
 | 2752 |                       w = 20; | 
 | 2753 |                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w; | 
 | 2754 |                     for (i = 0; i < w; i++) | 
 | 2755 |                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i]; | 
 | 2756 |                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0; | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 2757 |                     len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2758 |                     w = fax_parms[5].length; | 
 | 2759 |                     if (w > 20) | 
 | 2760 |                       w = 20; | 
 | 2761 |                     plci->fax_connect_info_buffer[len++] = (byte) w; | 
 | 2762 |                     for (i = 0; i < w; i++) | 
 | 2763 |                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i]; | 
 | 2764 |                     w = fax_parms[6].length; | 
 | 2765 |                     if (w > 20) | 
 | 2766 |                       w = 20; | 
 | 2767 |                     plci->fax_connect_info_buffer[len++] = (byte) w; | 
 | 2768 |                     for (i = 0; i < w; i++) | 
 | 2769 |                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i]; | 
 | 2770 |                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1]) | 
 | 2771 |                       & (1L << PRIVATE_FAX_NONSTANDARD)) | 
 | 2772 |       { | 
 | 2773 |                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms)) | 
 | 2774 |         { | 
 | 2775 |                         dbug(1,dprintf("non-standard facilities info missing or wrong format")); | 
 | 2776 |                         plci->fax_connect_info_buffer[len++] = 0; | 
 | 2777 |         } | 
 | 2778 |                       else | 
 | 2779 |                       { | 
 | 2780 |           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) | 
 | 2781 |             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); | 
 | 2782 |    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); | 
 | 2783 |           for (i = 0; i < fax_parms[7].length; i++) | 
 | 2784 |      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; | 
 | 2785 |                       } | 
 | 2786 |                     } | 
 | 2787 |                   } | 
 | 2788 |                 } | 
 | 2789 |                 else | 
 | 2790 |                 { | 
| Jiri Slaby | 1ea7084 | 2009-11-04 08:28:12 -0800 | [diff] [blame] | 2791 |                   len = offsetof(T30_INFO, universal_6); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2792 |                 } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2793 |                 fax_info_change = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2794 |  | 
 | 2795 |               } | 
 | 2796 |               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low)) | 
 | 2797 |               { | 
 | 2798 |                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2799 |                 fax_info_change = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2800 |               } | 
 | 2801 |             } | 
 | 2802 |             if (Info == GOOD) | 
 | 2803 |             { | 
 | 2804 |               plci->fax_connect_info_length = len; | 
 | 2805 |               if (fax_info_change) | 
 | 2806 |               { | 
 | 2807 |                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS) | 
 | 2808 |                 { | 
 | 2809 |                   start_internal_command (Id, plci, fax_connect_info_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2810 |                   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2811 |                 } | 
 | 2812 |                 else | 
 | 2813 |                 { | 
 | 2814 |                   start_internal_command (Id, plci, fax_adjust_b23_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2815 |                   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2816 |                 } | 
 | 2817 |               } | 
 | 2818 |             } | 
 | 2819 |           } | 
 | 2820 |           else  Info = _WRONG_STATE; | 
 | 2821 |         } | 
 | 2822 |         else  Info = _WRONG_STATE; | 
 | 2823 |       } | 
 | 2824 |  | 
 | 2825 |       else if (plci->B3_prot == B3_RTP) | 
 | 2826 |       { | 
 | 2827 |         plci->internal_req_buffer[0] = ncpi->length + 1; | 
 | 2828 |         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE; | 
 | 2829 |         for (w = 0; w < ncpi->length; w++) | 
 | 2830 |           plci->internal_req_buffer[2+w] = ncpi->info[1+w]; | 
 | 2831 |         start_internal_command (Id, plci, rtp_connect_b3_req_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2832 |         return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2833 |       } | 
 | 2834 |  | 
 | 2835 |       if(!Info) | 
 | 2836 |       { | 
 | 2837 |         nl_req_ncci(plci,req,0); | 
 | 2838 |         return 1; | 
 | 2839 |       } | 
 | 2840 |     } | 
 | 2841 |   } | 
 | 2842 |   else Info = _WRONG_IDENTIFIER; | 
 | 2843 |  | 
 | 2844 |   sendf(appl, | 
 | 2845 |         _CONNECT_B3_R|CONFIRM, | 
 | 2846 |         Id, | 
 | 2847 |         Number, | 
 | 2848 |         "w",Info); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2849 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2850 | } | 
 | 2851 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 2852 | static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 2853 | 			   PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2854 | { | 
 | 2855 |   word ncci; | 
 | 2856 |   API_PARSE * ncpi; | 
 | 2857 |   byte req; | 
 | 2858 |  | 
 | 2859 |   word w; | 
 | 2860 |  | 
 | 2861 |  | 
 | 2862 |     API_PARSE fax_parms[9]; | 
 | 2863 |   word i; | 
 | 2864 |   byte len; | 
 | 2865 |  | 
 | 2866 |  | 
 | 2867 |   dbug(1,dprintf("connect_b3_res")); | 
 | 2868 |  | 
 | 2869 |   ncci = (word)(Id>>16); | 
 | 2870 |   if(plci && ncci) { | 
 | 2871 |     if(a->ncci_state[ncci]==INC_CON_PENDING) { | 
 | 2872 |       if (GET_WORD (&parms[0].info[0]) != 0) | 
 | 2873 |       { | 
 | 2874 |         a->ncci_state[ncci] = OUTG_REJ_PENDING; | 
 | 2875 |         channel_request_xon (plci, a->ncci_ch[ncci]); | 
 | 2876 |         channel_xmit_xon (plci); | 
 | 2877 |         cleanup_ncci_data (plci, ncci); | 
 | 2878 |         nl_req_ncci(plci,N_DISC,(byte)ncci); | 
 | 2879 |         return 1; | 
 | 2880 |       } | 
 | 2881 |       a->ncci_state[ncci] = INC_ACT_PENDING; | 
 | 2882 |  | 
 | 2883 |       req = N_CONNECT_ACK; | 
 | 2884 |       ncpi = &parms[1]; | 
 | 2885 |       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7)) | 
 | 2886 |       { | 
 | 2887 |  | 
 | 2888 |         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) | 
 | 2889 |           & (1L << PRIVATE_FAX_NONSTANDARD)) | 
 | 2890 |  { | 
 | 2891 |    if (((plci->B3_prot == 4) || (plci->B3_prot == 5)) | 
 | 2892 |     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) | 
 | 2893 |     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) | 
 | 2894 |    { | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 2895 |             len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2896 |             if (plci->fax_connect_info_length < len) | 
 | 2897 |             { | 
 | 2898 |               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; | 
 | 2899 |               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; | 
 | 2900 |             } | 
 | 2901 |             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms)) | 
 | 2902 |             { | 
 | 2903 |               dbug(1,dprintf("non-standard facilities info missing or wrong format")); | 
 | 2904 |             } | 
 | 2905 |             else | 
 | 2906 |             { | 
 | 2907 |               if (plci->fax_connect_info_length <= len) | 
 | 2908 |                 plci->fax_connect_info_buffer[len] = 0; | 
 | 2909 |               len += 1 + plci->fax_connect_info_buffer[len]; | 
 | 2910 |               if (plci->fax_connect_info_length <= len) | 
 | 2911 |                 plci->fax_connect_info_buffer[len] = 0; | 
 | 2912 |               len += 1 + plci->fax_connect_info_buffer[len]; | 
 | 2913 |               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) | 
 | 2914 |                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); | 
 | 2915 |               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); | 
 | 2916 |               for (i = 0; i < fax_parms[7].length; i++) | 
 | 2917 |                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; | 
 | 2918 |             } | 
 | 2919 |             plci->fax_connect_info_length = len; | 
 | 2920 |             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0; | 
 | 2921 |             start_internal_command (Id, plci, fax_connect_ack_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2922 |      return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2923 |           } | 
 | 2924 |         } | 
 | 2925 |  | 
 | 2926 |         nl_req_ncci(plci,req,(byte)ncci); | 
 | 2927 |         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 2928 |          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | 
 | 2929 |         { | 
 | 2930 |           if (plci->B3_prot == 4) | 
 | 2931 |             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | 
 | 2932 |           else | 
 | 2933 |             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | 
 | 2934 |           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | 
 | 2935 |         } | 
 | 2936 |       } | 
 | 2937 |  | 
 | 2938 |       else if (plci->B3_prot == B3_RTP) | 
 | 2939 |       { | 
 | 2940 |         plci->internal_req_buffer[0] = ncpi->length + 1; | 
 | 2941 |         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE; | 
 | 2942 |         for (w = 0; w < ncpi->length; w++) | 
 | 2943 |           plci->internal_req_buffer[2+w] = ncpi->info[1+w]; | 
 | 2944 |         start_internal_command (Id, plci, rtp_connect_b3_res_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2945 |         return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2946 |       } | 
 | 2947 |  | 
 | 2948 |       else | 
 | 2949 |       { | 
 | 2950 |         if(ncpi->length>2) { | 
 | 2951 |           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT; | 
 | 2952 |           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]); | 
 | 2953 |         } | 
 | 2954 |         nl_req_ncci(plci,req,(byte)ncci); | 
 | 2955 |         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | 
 | 2956 |         if (plci->adjust_b_restore) | 
 | 2957 |         { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2958 |           plci->adjust_b_restore = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2959 |           start_internal_command (Id, plci, adjust_b_restore); | 
 | 2960 |         } | 
 | 2961 |       } | 
 | 2962 |       return 1; | 
 | 2963 |     } | 
 | 2964 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2965 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2966 | } | 
 | 2967 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 2968 | static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 2969 | 			     PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2970 | { | 
 | 2971 |   word ncci; | 
 | 2972 |  | 
 | 2973 |   ncci = (word)(Id>>16); | 
 | 2974 |   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci)); | 
 | 2975 |  | 
 | 2976 |   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING) | 
 | 2977 |    && (plci->State != OUTG_DIS_PENDING)) | 
 | 2978 |   { | 
 | 2979 |     if(a->ncci_state[ncci]==INC_ACT_PENDING) { | 
 | 2980 |       a->ncci_state[ncci] = CONNECTED; | 
 | 2981 |       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED; | 
 | 2982 |       channel_request_xon (plci, a->ncci_ch[ncci]); | 
 | 2983 |       channel_xmit_xon (plci); | 
 | 2984 |     } | 
 | 2985 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 2986 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2987 | } | 
 | 2988 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 2989 | static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 2990 | 			      PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2991 | { | 
 | 2992 |   word Info; | 
 | 2993 |   word ncci; | 
 | 2994 |   API_PARSE * ncpi; | 
 | 2995 |  | 
 | 2996 |   dbug(1,dprintf("disconnect_b3_req")); | 
 | 2997 |  | 
 | 2998 |   Info = _WRONG_IDENTIFIER; | 
 | 2999 |   ncci = (word)(Id>>16); | 
 | 3000 |   if (plci && ncci) | 
 | 3001 |   { | 
 | 3002 |     Info = _WRONG_STATE; | 
 | 3003 |     if ((a->ncci_state[ncci] == CONNECTED) | 
 | 3004 |      || (a->ncci_state[ncci] == OUTG_CON_PENDING) | 
 | 3005 |      || (a->ncci_state[ncci] == INC_CON_PENDING) | 
 | 3006 |      || (a->ncci_state[ncci] == INC_ACT_PENDING)) | 
 | 3007 |     { | 
 | 3008 |       a->ncci_state[ncci] = OUTG_DIS_PENDING; | 
 | 3009 |       channel_request_xon (plci, a->ncci_ch[ncci]); | 
 | 3010 |       channel_xmit_xon (plci); | 
 | 3011 |  | 
 | 3012 |       if (a->ncci[ncci].data_pending | 
 | 3013 |        && ((plci->B3_prot == B3_TRANSPARENT) | 
 | 3014 |         || (plci->B3_prot == B3_T30) | 
 | 3015 |         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS))) | 
 | 3016 |       { | 
 | 3017 |         plci->send_disc = (byte)ncci; | 
 | 3018 |         plci->command = 0; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3019 |         return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3020 |       } | 
 | 3021 |       else | 
 | 3022 |       { | 
 | 3023 |         cleanup_ncci_data (plci, ncci); | 
 | 3024 |  | 
 | 3025 |         if(plci->B3_prot==2 || plci->B3_prot==3) | 
 | 3026 |         { | 
 | 3027 |           ncpi = &parms[0]; | 
 | 3028 |           if(ncpi->length>3) | 
 | 3029 |           { | 
 | 3030 |             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4])); | 
 | 3031 |           } | 
 | 3032 |         } | 
 | 3033 |         nl_req_ncci(plci,N_DISC,(byte)ncci); | 
 | 3034 |       } | 
 | 3035 |       return 1; | 
 | 3036 |     } | 
 | 3037 |   } | 
 | 3038 |   sendf(appl, | 
 | 3039 |         _DISCONNECT_B3_R|CONFIRM, | 
 | 3040 |         Id, | 
 | 3041 |         Number, | 
 | 3042 |         "w",Info); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3043 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3044 | } | 
 | 3045 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 3046 | static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3047 | 			      PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3048 | { | 
 | 3049 |   word ncci; | 
 | 3050 |   word i; | 
 | 3051 |  | 
 | 3052 |   ncci = (word)(Id>>16); | 
 | 3053 |   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci)); | 
 | 3054 |   if(plci && ncci) { | 
 | 3055 |     plci->requested_options_conn = 0; | 
 | 3056 |     plci->fax_connect_info_length = 0; | 
 | 3057 |     plci->ncpi_state = 0x00; | 
 | 3058 |     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)) | 
 | 3059 |       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))) | 
 | 3060 |     { | 
 | 3061 |       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; | 
 | 3062 |     } | 
 | 3063 |     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++); | 
 | 3064 |     if(i<MAX_CHANNELS_PER_PLCI) { | 
 | 3065 |       if(plci->channels)plci->channels--; | 
 | 3066 |       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1]; | 
 | 3067 |       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0; | 
 | 3068 |  | 
 | 3069 |       ncci_free_receive_buffers (plci, ncci); | 
 | 3070 |  | 
 | 3071 |       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){ | 
 | 3072 |         if(plci->State == SUSPENDING){ | 
 | 3073 |           sendf(plci->appl, | 
 | 3074 |                 _FACILITY_I, | 
 | 3075 |                 Id & 0xffffL, | 
 | 3076 |                 0, | 
 | 3077 |                 "ws", (word)3, "\x03\x04\x00\x00"); | 
 | 3078 |           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0); | 
 | 3079 |         } | 
 | 3080 |         plci_remove(plci); | 
 | 3081 |         plci->State=IDLE; | 
 | 3082 |       } | 
 | 3083 |     } | 
 | 3084 |     else | 
 | 3085 |     { | 
 | 3086 |       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | 
 | 3087 |        && ((plci->B3_prot == 4) || (plci->B3_prot == 5)) | 
 | 3088 |        && (a->ncci_state[ncci] == INC_DIS_PENDING)) | 
 | 3089 |       { | 
 | 3090 |         ncci_free_receive_buffers (plci, ncci); | 
 | 3091 |  | 
 | 3092 |         nl_req_ncci(plci,N_EDATA,(byte)ncci); | 
 | 3093 |  | 
 | 3094 |         plci->adapter->ncci_state[ncci] = IDLE; | 
 | 3095 |         start_internal_command (Id, plci, fax_disconnect_command); | 
 | 3096 |         return 1; | 
 | 3097 |       } | 
 | 3098 |     } | 
 | 3099 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3100 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3101 | } | 
 | 3102 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 3103 | static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3104 | 			PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3105 | { | 
 | 3106 |   NCCI   *ncci_ptr; | 
 | 3107 |   DATA_B3_DESC   *data; | 
 | 3108 |   word Info; | 
 | 3109 |   word ncci; | 
 | 3110 |   word i; | 
 | 3111 |  | 
 | 3112 |   dbug(1,dprintf("data_b3_req")); | 
 | 3113 |  | 
 | 3114 |   Info = _WRONG_IDENTIFIER; | 
 | 3115 |   ncci = (word)(Id>>16); | 
 | 3116 |   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci)); | 
 | 3117 |  | 
 | 3118 |   if (plci && ncci) | 
 | 3119 |   { | 
 | 3120 |     Info = _WRONG_STATE; | 
 | 3121 |     if ((a->ncci_state[ncci] == CONNECTED) | 
 | 3122 |      || (a->ncci_state[ncci] == INC_ACT_PENDING)) | 
 | 3123 |     { | 
 | 3124 |         /* queue data */ | 
 | 3125 |       ncci_ptr = &(a->ncci[ncci]); | 
 | 3126 |       i = ncci_ptr->data_out + ncci_ptr->data_pending; | 
 | 3127 |       if (i >= MAX_DATA_B3) | 
 | 3128 |         i -= MAX_DATA_B3; | 
 | 3129 |       data = &(ncci_ptr->DBuffer[i]); | 
 | 3130 |       data->Number = Number; | 
 | 3131 |       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue))) | 
 | 3132 |        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | 
 | 3133 |       { | 
 | 3134 |  | 
| Andrew Morton | d3c8bdf | 2007-05-23 13:58:22 -0700 | [diff] [blame] | 3135 |         data->P = (byte *)(long)(*((dword *)(parms[0].info))); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3136 |  | 
 | 3137 |       } | 
 | 3138 |       else | 
 | 3139 |         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info); | 
 | 3140 |       data->Length = GET_WORD(parms[1].info); | 
 | 3141 |       data->Handle = GET_WORD(parms[2].info); | 
 | 3142 |       data->Flags = GET_WORD(parms[3].info); | 
 | 3143 |       (ncci_ptr->data_pending)++; | 
 | 3144 |  | 
 | 3145 |         /* check for delivery confirmation */ | 
 | 3146 |       if (data->Flags & 0x0004) | 
 | 3147 |       { | 
 | 3148 |         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending; | 
 | 3149 |         if (i >= MAX_DATA_ACK) | 
 | 3150 |           i -= MAX_DATA_ACK; | 
 | 3151 |         ncci_ptr->DataAck[i].Number = data->Number; | 
 | 3152 |         ncci_ptr->DataAck[i].Handle = data->Handle; | 
 | 3153 |         (ncci_ptr->data_ack_pending)++; | 
 | 3154 |       } | 
 | 3155 |  | 
 | 3156 |       send_data(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3157 |       return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3158 |     } | 
 | 3159 |   } | 
 | 3160 |   if (appl) | 
 | 3161 |   { | 
 | 3162 |     if (plci) | 
 | 3163 |     { | 
 | 3164 |       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue))) | 
 | 3165 |        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | 
 | 3166 |       { | 
 | 3167 |  | 
| Andrew Morton | d3c8bdf | 2007-05-23 13:58:22 -0700 | [diff] [blame] | 3168 |         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info)))); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3169 |  | 
 | 3170 |       } | 
 | 3171 |     } | 
 | 3172 |     sendf(appl, | 
 | 3173 |           _DATA_B3_R|CONFIRM, | 
 | 3174 |           Id, | 
 | 3175 |           Number, | 
 | 3176 |           "ww",GET_WORD(parms[2].info),Info); | 
 | 3177 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3178 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3179 | } | 
 | 3180 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 3181 | static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3182 | 			PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3183 | { | 
 | 3184 |   word n; | 
 | 3185 |   word ncci; | 
 | 3186 |   word NCCIcode; | 
 | 3187 |  | 
 | 3188 |   dbug(1,dprintf("data_b3_res")); | 
 | 3189 |  | 
 | 3190 |   ncci = (word)(Id>>16); | 
 | 3191 |   if(plci && ncci) { | 
 | 3192 |     n = GET_WORD(parms[0].info); | 
 | 3193 |     dbug(1,dprintf("free(%d)",n)); | 
 | 3194 |     NCCIcode = ncci | (((word) a->Id) << 8); | 
 | 3195 |     if(n<appl->MaxBuffer && | 
 | 3196 |        appl->DataNCCI[n]==NCCIcode && | 
 | 3197 |        (byte)(appl->DataFlags[n]>>8)==plci->Id) { | 
 | 3198 |       dbug(1,dprintf("found")); | 
 | 3199 |       appl->DataNCCI[n] = 0; | 
 | 3200 |  | 
 | 3201 |       if (channel_can_xon (plci, a->ncci_ch[ncci])) { | 
 | 3202 |         channel_request_xon (plci, a->ncci_ch[ncci]); | 
 | 3203 |       } | 
 | 3204 |       channel_xmit_xon (plci); | 
 | 3205 |  | 
 | 3206 |       if(appl->DataFlags[n] &4) { | 
 | 3207 |         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci); | 
 | 3208 |         return 1; | 
 | 3209 |       } | 
 | 3210 |     } | 
 | 3211 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3212 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3213 | } | 
 | 3214 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 3215 | static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3216 | 			 PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3217 | { | 
 | 3218 |   word Info; | 
 | 3219 |   word ncci; | 
 | 3220 |  | 
 | 3221 |   dbug(1,dprintf("reset_b3_req")); | 
 | 3222 |  | 
 | 3223 |   Info = _WRONG_IDENTIFIER; | 
 | 3224 |   ncci = (word)(Id>>16); | 
 | 3225 |   if(plci && ncci) | 
 | 3226 |   { | 
 | 3227 |     Info = _WRONG_STATE; | 
 | 3228 |     switch (plci->B3_prot) | 
 | 3229 |     { | 
 | 3230 |     case B3_ISO8208: | 
 | 3231 |     case B3_X25_DCE: | 
 | 3232 |       if(a->ncci_state[ncci]==CONNECTED) | 
 | 3233 |       { | 
 | 3234 |         nl_req_ncci(plci,N_RESET,(byte)ncci); | 
 | 3235 |         send_req(plci); | 
 | 3236 |         Info = GOOD; | 
 | 3237 |       } | 
 | 3238 |       break; | 
 | 3239 |     case B3_TRANSPARENT: | 
 | 3240 |       if(a->ncci_state[ncci]==CONNECTED) | 
 | 3241 |       { | 
 | 3242 |         start_internal_command (Id, plci, reset_b3_command); | 
 | 3243 |         Info = GOOD; | 
 | 3244 |       } | 
 | 3245 |       break; | 
 | 3246 |     } | 
 | 3247 |   } | 
 | 3248 |   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */ | 
 | 3249 |   sendf(appl, | 
 | 3250 |         _RESET_B3_R|CONFIRM, | 
 | 3251 |         Id, | 
 | 3252 |         Number, | 
 | 3253 |         "w",Info); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3254 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3255 | } | 
 | 3256 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 3257 | static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3258 | 			 PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3259 | { | 
 | 3260 |   word ncci; | 
 | 3261 |  | 
 | 3262 |   dbug(1,dprintf("reset_b3_res")); | 
 | 3263 |  | 
 | 3264 |   ncci = (word)(Id>>16); | 
 | 3265 |   if(plci && ncci) { | 
 | 3266 |     switch (plci->B3_prot) | 
 | 3267 |     { | 
 | 3268 |     case B3_ISO8208: | 
 | 3269 |     case B3_X25_DCE: | 
 | 3270 |       if(a->ncci_state[ncci]==INC_RES_PENDING) | 
 | 3271 |       { | 
 | 3272 |         a->ncci_state[ncci] = CONNECTED; | 
 | 3273 |         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3274 |         return true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3275 |       } | 
 | 3276 |     break; | 
 | 3277 |     } | 
 | 3278 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3279 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3280 | } | 
 | 3281 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 3282 | static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3283 | 				 PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3284 | { | 
 | 3285 |   word ncci; | 
 | 3286 |   API_PARSE * ncpi; | 
 | 3287 |   byte req; | 
 | 3288 |  | 
 | 3289 |   dbug(1,dprintf("connect_b3_t90_a_res")); | 
 | 3290 |  | 
 | 3291 |   ncci = (word)(Id>>16); | 
 | 3292 |   if(plci && ncci) { | 
 | 3293 |     if(a->ncci_state[ncci]==INC_ACT_PENDING) { | 
 | 3294 |       a->ncci_state[ncci] = CONNECTED; | 
 | 3295 |     } | 
 | 3296 |     else if(a->ncci_state[ncci]==INC_CON_PENDING) { | 
 | 3297 |       a->ncci_state[ncci] = CONNECTED; | 
 | 3298 |  | 
 | 3299 |       req = N_CONNECT_ACK; | 
 | 3300 |  | 
 | 3301 |         /* parms[0]==0 for CAPI original message definition! */ | 
 | 3302 |       if(parms[0].info) { | 
 | 3303 |         ncpi = &parms[1]; | 
 | 3304 |         if(ncpi->length>2) { | 
 | 3305 |           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT; | 
 | 3306 |           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]); | 
 | 3307 |         } | 
 | 3308 |       } | 
 | 3309 |       nl_req_ncci(plci,req,(byte)ncci); | 
 | 3310 |       return 1; | 
 | 3311 |     } | 
 | 3312 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3313 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3314 | } | 
 | 3315 |  | 
 | 3316 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 3317 | static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3318 | 			 PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3319 | { | 
 | 3320 |   word Info=0; | 
 | 3321 |   word i; | 
 | 3322 |   byte tel; | 
 | 3323 |     API_PARSE bp_parms[7]; | 
 | 3324 |  | 
 | 3325 |   if(!plci || !msg) | 
 | 3326 |   { | 
 | 3327 |     Info = _WRONG_IDENTIFIER; | 
 | 3328 |   } | 
 | 3329 |   else | 
 | 3330 |   { | 
 | 3331 |     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x", | 
 | 3332 |                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState)); | 
 | 3333 |     dbug(1,dprintf("PlciState=0x%x",plci->State)); | 
 | 3334 |     for(i=0;i<7;i++) bp_parms[i].length = 0; | 
 | 3335 |  | 
 | 3336 |     /* check if no channel is open, no B3 connected only */ | 
 | 3337 |     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING) | 
 | 3338 |      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id) | 
 | 3339 |     { | 
 | 3340 |       Info = _WRONG_STATE; | 
 | 3341 |     } | 
 | 3342 |     /* check message format and fill bp_parms pointer */ | 
 | 3343 |     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms)) | 
 | 3344 |     { | 
 | 3345 |       Info = _WRONG_MESSAGE_FORMAT; | 
 | 3346 |     } | 
 | 3347 |     else | 
 | 3348 |     { | 
 | 3349 |       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */ | 
 | 3350 |       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */ | 
 | 3351 |         if(Id & EXT_CONTROLLER) | 
 | 3352 |         { | 
 | 3353 |           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */ | 
 | 3354 |           return 0; | 
 | 3355 |         } | 
 | 3356 |         plci->State=INC_CON_CONNECTED_ALERT; | 
 | 3357 |         plci->appl = appl; | 
 | 3358 |         clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | 
 | 3359 |         dump_c_ind_mask (plci); | 
 | 3360 |         for(i=0; i<max_appl; i++) /* disconnect the other appls */ | 
 | 3361 |         {                         /* its quasi a connect        */ | 
 | 3362 |           if(test_c_ind_mask_bit (plci, i)) | 
 | 3363 |             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED); | 
 | 3364 |         } | 
 | 3365 |       } | 
 | 3366 |  | 
 | 3367 |       api_save_msg(msg, "s", &plci->saved_msg); | 
 | 3368 |       tel = plci->tel; | 
 | 3369 |       if(Id & EXT_CONTROLLER) | 
 | 3370 |       { | 
 | 3371 |         if(tel) /* external controller in use by this PLCI */ | 
 | 3372 |         { | 
 | 3373 |           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl) | 
 | 3374 |           { | 
 | 3375 |             dbug(1,dprintf("Ext_Ctrl in use 1")); | 
 | 3376 |             Info = _WRONG_STATE; | 
 | 3377 |           } | 
 | 3378 |         } | 
 | 3379 |         else  /* external controller NOT in use by this PLCI ? */ | 
 | 3380 |         { | 
 | 3381 |           if(a->AdvSignalPLCI) | 
 | 3382 |           { | 
 | 3383 |             dbug(1,dprintf("Ext_Ctrl in use 2")); | 
 | 3384 |             Info = _WRONG_STATE; | 
 | 3385 |           } | 
 | 3386 |           else /* activate the codec */ | 
 | 3387 |           { | 
 | 3388 |             dbug(1,dprintf("Ext_Ctrl start")); | 
 | 3389 |             if(AdvCodecSupport(a, plci, appl, 0) ) | 
 | 3390 |             { | 
 | 3391 |               dbug(1,dprintf("Error in codec procedures")); | 
 | 3392 |               Info = _WRONG_STATE; | 
 | 3393 |             } | 
 | 3394 |             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */ | 
 | 3395 |             { | 
 | 3396 |               plci->spoofed_msg = AWAITING_SELECT_B; | 
 | 3397 |               plci->internal_command = BLOCK_PLCI; /* lock other commands */ | 
 | 3398 |               plci->command = 0; | 
 | 3399 |               dbug(1,dprintf("continue if codec loaded")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3400 |               return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3401 |             } | 
 | 3402 |           } | 
 | 3403 |         } | 
 | 3404 |       } | 
 | 3405 |       else /* external controller bit is OFF */ | 
 | 3406 |       { | 
 | 3407 |         if(tel) /* external controller in use, need to switch off */ | 
 | 3408 |         { | 
 | 3409 |           if(a->AdvSignalAppl==appl) | 
 | 3410 |           { | 
 | 3411 |             CodecIdCheck(a, plci); | 
 | 3412 |             plci->tel = 0; | 
 | 3413 |             plci->adv_nl = 0; | 
 | 3414 |             dbug(1,dprintf("Ext_Ctrl disable")); | 
 | 3415 |           } | 
 | 3416 |           else | 
 | 3417 |           { | 
 | 3418 |             dbug(1,dprintf("Ext_Ctrl not requested")); | 
 | 3419 |           } | 
 | 3420 |         } | 
 | 3421 |       } | 
 | 3422 |       if (!Info) | 
 | 3423 |       { | 
 | 3424 |         if (plci->call_dir & CALL_DIR_OUT) | 
 | 3425 |           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | 
 | 3426 |         else if (plci->call_dir & CALL_DIR_IN) | 
 | 3427 |           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER; | 
 | 3428 |         start_internal_command (Id, plci, select_b_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3429 |         return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3430 |       } | 
 | 3431 |     } | 
 | 3432 |   } | 
 | 3433 |   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3434 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3435 | } | 
 | 3436 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 3437 | static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3438 | 			     PLCI *plci, APPL *appl, API_PARSE *parms) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3439 | { | 
 | 3440 |   word command; | 
 | 3441 |   word i; | 
 | 3442 |   word ncci; | 
 | 3443 |   API_PARSE * m; | 
 | 3444 |     API_PARSE m_parms[5]; | 
 | 3445 |   word codec; | 
 | 3446 |   byte req; | 
 | 3447 |   byte ch; | 
 | 3448 |   byte dir; | 
 | 3449 |   static byte chi[2] = {0x01,0x00}; | 
 | 3450 |   static byte lli[2] = {0x01,0x00}; | 
 | 3451 |   static byte codec_cai[2] = {0x01,0x01}; | 
 | 3452 |   static byte null_msg = {0}; | 
 | 3453 |   static API_PARSE null_parms = { 0, &null_msg }; | 
 | 3454 |   PLCI   * v_plci; | 
 | 3455 |   word Info=0; | 
 | 3456 |  | 
 | 3457 |   dbug(1,dprintf("manufacturer_req")); | 
 | 3458 |   for(i=0;i<5;i++) m_parms[i].length = 0; | 
 | 3459 |  | 
 | 3460 |   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) { | 
 | 3461 |     Info = _WRONG_MESSAGE_FORMAT; | 
 | 3462 |   } | 
 | 3463 |   command = GET_WORD(parms[1].info); | 
 | 3464 |   m = &parms[2]; | 
 | 3465 |   if (!Info) | 
 | 3466 |   { | 
 | 3467 |     switch(command) { | 
 | 3468 |     case _DI_ASSIGN_PLCI: | 
 | 3469 |       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) { | 
 | 3470 |         Info = _WRONG_MESSAGE_FORMAT; | 
 | 3471 |         break; | 
 | 3472 |       } | 
 | 3473 |       codec = GET_WORD(m_parms[0].info); | 
 | 3474 |       ch = m_parms[1].info[0]; | 
 | 3475 |       dir = m_parms[2].info[0]; | 
 | 3476 |       if((i=get_plci(a))) { | 
 | 3477 |         plci = &a->plci[i-1]; | 
 | 3478 |         plci->appl = appl; | 
 | 3479 |         plci->command = _MANUFACTURER_R; | 
 | 3480 |         plci->m_command = command; | 
 | 3481 |         plci->number = Number; | 
 | 3482 |         plci->State = LOCAL_CONNECT; | 
 | 3483 |         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80); | 
 | 3484 |         dbug(1,dprintf("ManCMD,plci=0x%x",Id)); | 
 | 3485 |  | 
 | 3486 |         if((ch==1 || ch==2) && (dir<=2)) { | 
 | 3487 |           chi[1] = (byte)(0x80|ch); | 
 | 3488 |           lli[1] = 0; | 
 | 3489 |           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | 
 | 3490 |           switch(codec) | 
 | 3491 |           { | 
 | 3492 |           case 0: | 
 | 3493 |             Info = add_b1(plci,&m_parms[3],0,0); | 
 | 3494 |             break; | 
 | 3495 |           case 1: | 
 | 3496 |             add_p(plci,CAI,codec_cai); | 
 | 3497 |             break; | 
 | 3498 |           /* manual 'swich on' to the codec support without signalling */ | 
 | 3499 |           /* first 'assign plci' with this function, then use */ | 
 | 3500 |           case 2: | 
 | 3501 |             if(AdvCodecSupport(a, plci, appl, 0) ) { | 
 | 3502 |               Info = _RESOURCE_ERROR; | 
 | 3503 |             } | 
 | 3504 |             else { | 
 | 3505 |               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL); | 
 | 3506 |               lli[1] = 0x10; /* local call codec stream */ | 
 | 3507 |             } | 
 | 3508 |             break; | 
 | 3509 |           } | 
 | 3510 |  | 
 | 3511 |           plci->State = LOCAL_CONNECT; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3512 |           plci->manufacturer = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3513 |           plci->command = _MANUFACTURER_R; | 
 | 3514 |           plci->m_command = command; | 
 | 3515 |           plci->number = Number; | 
 | 3516 |  | 
 | 3517 |           if(!Info) | 
 | 3518 |           { | 
 | 3519 |             add_p(plci,LLI,lli); | 
 | 3520 |             add_p(plci,CHI,chi); | 
 | 3521 |             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 3522 |             sig_req(plci,ASSIGN,DSIG_ID); | 
 | 3523 |  | 
 | 3524 |             if(!codec) | 
 | 3525 |             { | 
 | 3526 |               Info = add_b23(plci,&m_parms[3]); | 
 | 3527 |               if(!Info) | 
 | 3528 |               { | 
 | 3529 |                 nl_req_ncci(plci,ASSIGN,0); | 
 | 3530 |                 send_req(plci); | 
 | 3531 |               } | 
 | 3532 |             } | 
 | 3533 |             if(!Info) | 
 | 3534 |             { | 
 | 3535 |               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg)); | 
 | 3536 |               if (plci->spoofed_msg==SPOOFING_REQUIRED) | 
 | 3537 |               { | 
 | 3538 |                 api_save_msg (m_parms, "wbbs", &plci->saved_msg); | 
 | 3539 |                 plci->spoofed_msg = AWAITING_MANUF_CON; | 
 | 3540 |                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */ | 
 | 3541 |                 plci->command = 0; | 
 | 3542 |                 send_req(plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3543 |                 return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3544 |               } | 
 | 3545 |               if(dir==1) { | 
 | 3546 |                 sig_req(plci,CALL_REQ,0); | 
 | 3547 |               } | 
 | 3548 |               else if(!dir){ | 
 | 3549 |                 sig_req(plci,LISTEN_REQ,0); | 
 | 3550 |               } | 
 | 3551 |               send_req(plci); | 
 | 3552 |             } | 
 | 3553 |             else | 
 | 3554 |             { | 
 | 3555 |               sendf(appl, | 
 | 3556 |                     _MANUFACTURER_R|CONFIRM, | 
 | 3557 |                     Id, | 
 | 3558 |                     Number, | 
 | 3559 |                     "dww",_DI_MANU_ID,command,Info); | 
 | 3560 |               return 2; | 
 | 3561 |             } | 
 | 3562 |           } | 
 | 3563 |         } | 
 | 3564 |       } | 
 | 3565 |       else  Info = _OUT_OF_PLCI; | 
 | 3566 |       break; | 
 | 3567 |  | 
 | 3568 |     case _DI_IDI_CTRL: | 
 | 3569 |       if(!plci) | 
 | 3570 |       { | 
 | 3571 |         Info = _WRONG_IDENTIFIER; | 
 | 3572 |         break; | 
 | 3573 |       } | 
 | 3574 |       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) { | 
 | 3575 |         Info = _WRONG_MESSAGE_FORMAT; | 
 | 3576 |         break; | 
 | 3577 |       } | 
 | 3578 |       req = m_parms[0].info[0]; | 
 | 3579 |       plci->command = _MANUFACTURER_R; | 
 | 3580 |       plci->m_command = command; | 
 | 3581 |       plci->number = Number; | 
 | 3582 |       if(req==CALL_REQ) | 
 | 3583 |       { | 
 | 3584 |         plci->b_channel = getChannel(&m_parms[1]); | 
 | 3585 |         mixer_set_bchannel_id_esc (plci, plci->b_channel); | 
 | 3586 |         if(plci->spoofed_msg==SPOOFING_REQUIRED) | 
 | 3587 |         { | 
 | 3588 |           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON; | 
 | 3589 |           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */ | 
 | 3590 |           plci->command = 0; | 
 | 3591 |           break; | 
 | 3592 |         } | 
 | 3593 |       } | 
 | 3594 |       else if(req==LAW_REQ) | 
 | 3595 |       { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3596 |         plci->cr_enquiry = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3597 |       } | 
 | 3598 |       add_ss(plci,FTY,&m_parms[1]); | 
 | 3599 |       sig_req(plci,req,0); | 
 | 3600 |       send_req(plci); | 
 | 3601 |       if(req==HANGUP) | 
 | 3602 |       {       | 
 | 3603 |         if (plci->NL.Id && !plci->nl_remove_id) | 
 | 3604 |         { | 
 | 3605 |           if (plci->channels) | 
 | 3606 |           { | 
 | 3607 |             for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | 
 | 3608 |             { | 
 | 3609 |               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED)) | 
 | 3610 |               { | 
 | 3611 |                 a->ncci_state[ncci] = OUTG_DIS_PENDING; | 
 | 3612 |                 cleanup_ncci_data (plci, ncci); | 
 | 3613 |                 nl_req_ncci(plci,N_DISC,(byte)ncci); | 
 | 3614 |               } | 
 | 3615 |             } | 
 | 3616 |           } | 
 | 3617 |           mixer_remove (plci); | 
 | 3618 |           nl_req_ncci(plci,REMOVE,0); | 
 | 3619 |           send_req(plci); | 
 | 3620 |         }   | 
 | 3621 |       } | 
 | 3622 |       break; | 
 | 3623 |  | 
 | 3624 |     case _DI_SIG_CTRL: | 
 | 3625 |     /* signalling control for loop activation B-channel */ | 
 | 3626 |       if(!plci) | 
 | 3627 |       { | 
 | 3628 |         Info = _WRONG_IDENTIFIER; | 
 | 3629 |         break; | 
 | 3630 |       } | 
 | 3631 |       if(m->length){ | 
 | 3632 |         plci->command = _MANUFACTURER_R; | 
 | 3633 |         plci->number = Number; | 
 | 3634 |         add_ss(plci,FTY,m); | 
 | 3635 |         sig_req(plci,SIG_CTRL,0); | 
 | 3636 |         send_req(plci); | 
 | 3637 |       } | 
 | 3638 |       else Info = _WRONG_MESSAGE_FORMAT; | 
 | 3639 |       break; | 
 | 3640 |  | 
 | 3641 |     case _DI_RXT_CTRL: | 
 | 3642 |     /* activation control for receiver/transmitter B-channel */ | 
 | 3643 |       if(!plci) | 
 | 3644 |       { | 
 | 3645 |         Info = _WRONG_IDENTIFIER; | 
 | 3646 |         break; | 
 | 3647 |       } | 
 | 3648 |       if(m->length){ | 
 | 3649 |         plci->command = _MANUFACTURER_R; | 
 | 3650 |         plci->number = Number; | 
 | 3651 |         add_ss(plci,FTY,m); | 
 | 3652 |         sig_req(plci,DSP_CTRL,0); | 
 | 3653 |         send_req(plci); | 
 | 3654 |       } | 
 | 3655 |       else Info = _WRONG_MESSAGE_FORMAT; | 
 | 3656 |       break; | 
 | 3657 |  | 
 | 3658 |     case _DI_ADV_CODEC: | 
 | 3659 |     case _DI_DSP_CTRL: | 
 | 3660 |       /* TEL_CTRL commands to support non standard adjustments: */ | 
 | 3661 |       /* Ring on/off, Handset micro volume, external micro vol. */ | 
 | 3662 |       /* handset+external speaker volume, receiver+transm. gain,*/ | 
 | 3663 |       /* handsfree on (hookinfo off), set mixer command         */ | 
 | 3664 |  | 
 | 3665 |       if(command == _DI_ADV_CODEC) | 
 | 3666 |       { | 
 | 3667 |         if(!a->AdvCodecPLCI) { | 
 | 3668 |           Info = _WRONG_STATE; | 
 | 3669 |           break; | 
 | 3670 |         } | 
 | 3671 |         v_plci = a->AdvCodecPLCI; | 
 | 3672 |       } | 
 | 3673 |       else | 
 | 3674 |       { | 
 | 3675 |         if (plci | 
 | 3676 |          && (m->length >= 3) | 
 | 3677 |          && (m->info[1] == 0x1c) | 
 | 3678 |          && (m->info[2] >= 1)) | 
 | 3679 |         { | 
 | 3680 |           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS) | 
 | 3681 |           { | 
 | 3682 |             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI)) | 
 | 3683 |             { | 
 | 3684 |               Info = _WRONG_STATE; | 
 | 3685 |               break; | 
 | 3686 |             } | 
 | 3687 |             a->adv_voice_coef_length = m->info[2] - 1; | 
 | 3688 |             if (a->adv_voice_coef_length > m->length - 3) | 
 | 3689 |               a->adv_voice_coef_length = (byte)(m->length - 3); | 
 | 3690 |             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE) | 
 | 3691 |               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE; | 
 | 3692 |             for (i = 0; i < a->adv_voice_coef_length; i++) | 
 | 3693 |               a->adv_voice_coef_buffer[i] = m->info[4 + i]; | 
 | 3694 |             if (plci->B1_facilities & B1_FACILITY_VOICE) | 
 | 3695 |               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE); | 
 | 3696 |             break; | 
 | 3697 |           } | 
 | 3698 |           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS) | 
 | 3699 |           { | 
 | 3700 |             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS)) | 
 | 3701 |             { | 
 | 3702 |               Info = _FACILITY_NOT_SUPPORTED; | 
 | 3703 |               break; | 
 | 3704 |             } | 
 | 3705 |  | 
 | 3706 |             plci->dtmf_parameter_length = m->info[2] - 1; | 
 | 3707 |             if (plci->dtmf_parameter_length > m->length - 3) | 
 | 3708 |               plci->dtmf_parameter_length = (byte)(m->length - 3); | 
 | 3709 |             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE) | 
 | 3710 |               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE; | 
 | 3711 |             for (i = 0; i < plci->dtmf_parameter_length; i++) | 
 | 3712 |               plci->dtmf_parameter_buffer[i] = m->info[4+i]; | 
 | 3713 |             if (plci->B1_facilities & B1_FACILITY_DTMFR) | 
 | 3714 |               dtmf_parameter_write (plci); | 
 | 3715 |             break; | 
 | 3716 |  | 
 | 3717 |           } | 
 | 3718 |         } | 
 | 3719 |         v_plci = plci; | 
 | 3720 |       } | 
 | 3721 |  | 
 | 3722 |       if(!v_plci) | 
 | 3723 |       { | 
 | 3724 |         Info = _WRONG_IDENTIFIER; | 
 | 3725 |         break; | 
 | 3726 |       } | 
 | 3727 |       if(m->length){ | 
 | 3728 |         add_ss(v_plci,FTY,m); | 
 | 3729 |         sig_req(v_plci,TEL_CTRL,0); | 
 | 3730 |         send_req(v_plci); | 
 | 3731 |       } | 
 | 3732 |       else Info = _WRONG_MESSAGE_FORMAT; | 
 | 3733 |  | 
 | 3734 |       break; | 
 | 3735 |  | 
 | 3736 |     case _DI_OPTIONS_REQUEST: | 
 | 3737 |       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) { | 
 | 3738 |         Info = _WRONG_MESSAGE_FORMAT; | 
 | 3739 |         break; | 
 | 3740 |       } | 
 | 3741 |       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options) | 
 | 3742 |       { | 
 | 3743 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 3744 |         break; | 
 | 3745 |       } | 
 | 3746 |       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info); | 
 | 3747 |       break; | 
 | 3748 |  | 
 | 3749 |  | 
 | 3750 |  | 
 | 3751 |     default: | 
 | 3752 |       Info = _WRONG_MESSAGE_FORMAT; | 
 | 3753 |       break; | 
 | 3754 |     } | 
 | 3755 |   } | 
 | 3756 |  | 
 | 3757 |   sendf(appl, | 
 | 3758 |         _MANUFACTURER_R|CONFIRM, | 
 | 3759 |         Id, | 
 | 3760 |         Number, | 
 | 3761 |         "dww",_DI_MANU_ID,command,Info); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3762 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3763 | } | 
 | 3764 |  | 
 | 3765 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 3766 | static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | 
 | 3767 | 			     PLCI *plci, APPL *appl, API_PARSE *msg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3768 | { | 
 | 3769 |   word indication; | 
 | 3770 |  | 
 | 3771 |     API_PARSE m_parms[3]; | 
 | 3772 |   API_PARSE *ncpi; | 
 | 3773 |     API_PARSE fax_parms[9]; | 
 | 3774 |   word i; | 
 | 3775 |   byte len; | 
 | 3776 |  | 
 | 3777 |  | 
 | 3778 |   dbug(1,dprintf("manufacturer_res")); | 
 | 3779 |  | 
 | 3780 |   if ((msg[0].length == 0) | 
 | 3781 |    || (msg[1].length == 0) | 
 | 3782 |    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID)) | 
 | 3783 |   { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3784 |     return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3785 |   } | 
 | 3786 |   indication = GET_WORD(msg[1].info); | 
 | 3787 |   switch (indication) | 
 | 3788 |   { | 
 | 3789 |  | 
 | 3790 |   case _DI_NEGOTIATE_B3: | 
 | 3791 |     if(!plci) | 
 | 3792 |       break; | 
 | 3793 |     if (((plci->B3_prot != 4) && (plci->B3_prot != 5)) | 
 | 3794 |      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT)) | 
 | 3795 |     { | 
 | 3796 |       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters")); | 
 | 3797 |       break; | 
 | 3798 |     } | 
 | 3799 |     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms)) | 
 | 3800 |     { | 
 | 3801 |       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters")); | 
 | 3802 |       break; | 
 | 3803 |     } | 
 | 3804 |     ncpi = &m_parms[1]; | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 3805 |     len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3806 |     if (plci->fax_connect_info_length < len) | 
 | 3807 |     { | 
 | 3808 |       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; | 
 | 3809 |       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; | 
 | 3810 |     } | 
 | 3811 |     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms)) | 
 | 3812 |     { | 
 | 3813 |       dbug(1,dprintf("non-standard facilities info missing or wrong format")); | 
 | 3814 |     } | 
 | 3815 |     else | 
 | 3816 |     { | 
 | 3817 |       if (plci->fax_connect_info_length <= len) | 
 | 3818 |         plci->fax_connect_info_buffer[len] = 0; | 
 | 3819 |       len += 1 + plci->fax_connect_info_buffer[len]; | 
 | 3820 |       if (plci->fax_connect_info_length <= len) | 
 | 3821 |         plci->fax_connect_info_buffer[len] = 0; | 
 | 3822 |       len += 1 + plci->fax_connect_info_buffer[len]; | 
 | 3823 |       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) | 
 | 3824 |         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); | 
 | 3825 |       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); | 
 | 3826 |       for (i = 0; i < fax_parms[7].length; i++) | 
 | 3827 |         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; | 
 | 3828 |     } | 
 | 3829 |     plci->fax_connect_info_length = len; | 
 | 3830 |     plci->fax_edata_ack_length = plci->fax_connect_info_length; | 
 | 3831 |     start_internal_command (Id, plci, fax_edata_ack_command); | 
 | 3832 |     break; | 
 | 3833 |  | 
 | 3834 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3835 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3836 | } | 
 | 3837 |  | 
 | 3838 | /*------------------------------------------------------------------*/ | 
 | 3839 | /* IDI callback function                                            */ | 
 | 3840 | /*------------------------------------------------------------------*/ | 
 | 3841 |  | 
 | 3842 | void   callback(ENTITY   * e) | 
 | 3843 | { | 
 | 3844 |   DIVA_CAPI_ADAPTER   * a; | 
 | 3845 |   APPL   * appl; | 
 | 3846 |   PLCI   * plci; | 
 | 3847 |   CAPI_MSG   *m; | 
 | 3848 |   word i, j; | 
 | 3849 |   byte rc; | 
 | 3850 |   byte ch; | 
 | 3851 |   byte req; | 
 | 3852 |   byte global_req; | 
 | 3853 |   int no_cancel_rc; | 
 | 3854 |  | 
 | 3855 |   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)", | 
 | 3856 |                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind)); | 
 | 3857 |  | 
 | 3858 |   a = &(adapter[(byte)e->user[0]]); | 
 | 3859 |   plci = &(a->plci[e->user[1]]); | 
 | 3860 |   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a); | 
 | 3861 |  | 
 | 3862 |   /* | 
 | 3863 |      If new protocol code and new XDI is used then CAPI should work | 
 | 3864 |      fully in accordance with IDI cpec an look on callback field instead | 
 | 3865 |      of Rc field for return codes. | 
 | 3866 |    */ | 
 | 3867 |   if (((e->complete == 0xff) && no_cancel_rc) || | 
 | 3868 |       (e->Rc && !no_cancel_rc)) { | 
 | 3869 |     rc = e->Rc; | 
 | 3870 |     ch = e->RcCh; | 
 | 3871 |     req = e->Req; | 
 | 3872 |     e->Rc = 0; | 
 | 3873 |  | 
 | 3874 |     if (e->user[0] & 0x8000) | 
 | 3875 |     { | 
 | 3876 |       /* | 
 | 3877 |          If REMOVE request was sent then we have to wait until | 
 | 3878 |          return code with Id set to zero arrives. | 
 | 3879 |          All other return codes should be ignored. | 
 | 3880 |          */ | 
 | 3881 |       if (req == REMOVE) | 
 | 3882 |       { | 
 | 3883 |         if (e->Id) | 
 | 3884 |         { | 
 | 3885 |           dbug(1,dprintf("cancel RC in REMOVE state")); | 
 | 3886 |           return; | 
 | 3887 |         } | 
 | 3888 |         channel_flow_control_remove (plci); | 
 | 3889 |         for (i = 0; i < 256; i++) | 
 | 3890 |         { | 
 | 3891 |           if (a->FlowControlIdTable[i] == plci->nl_remove_id) | 
 | 3892 |             a->FlowControlIdTable[i] = 0; | 
 | 3893 |         } | 
 | 3894 |         plci->nl_remove_id = 0; | 
 | 3895 |         if (plci->rx_dma_descriptor > 0) { | 
 | 3896 |           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1); | 
 | 3897 |           plci->rx_dma_descriptor = 0; | 
 | 3898 |         } | 
 | 3899 |       } | 
 | 3900 |       if (rc == OK_FC) | 
 | 3901 |       { | 
 | 3902 |         a->FlowControlIdTable[ch] = e->Id; | 
 | 3903 |         a->FlowControlSkipTable[ch] = 0; | 
 | 3904 |  | 
 | 3905 |         a->ch_flow_control[ch] |= N_OK_FC_PENDING; | 
 | 3906 |         a->ch_flow_plci[ch] = plci->Id; | 
 | 3907 |         plci->nl_req = 0; | 
 | 3908 |       } | 
 | 3909 |       else | 
 | 3910 |       { | 
 | 3911 |         /* | 
 | 3912 |           Cancel return codes self, if feature was requested | 
 | 3913 |           */ | 
 | 3914 |         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) { | 
 | 3915 |           a->FlowControlIdTable[ch] = 0; | 
 | 3916 |           if ((rc == OK) && a->FlowControlSkipTable[ch]) { | 
 | 3917 |             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch)); | 
 | 3918 |             return; | 
 | 3919 |           } | 
 | 3920 |         } | 
 | 3921 |  | 
 | 3922 |         if (a->ch_flow_control[ch] & N_OK_FC_PENDING) | 
 | 3923 |         { | 
 | 3924 |           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING; | 
 | 3925 |           if (ch == e->ReqCh) | 
 | 3926 |             plci->nl_req = 0; | 
 | 3927 |         } | 
 | 3928 |         else | 
 | 3929 |           plci->nl_req = 0; | 
 | 3930 |       } | 
 | 3931 |       if (plci->nl_req) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3932 |         control_rc (plci, 0, rc, ch, 0, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3933 |       else | 
 | 3934 |       { | 
 | 3935 |         if (req == N_XON) | 
 | 3936 |         { | 
 | 3937 |           channel_x_on (plci, ch); | 
 | 3938 |           if (plci->internal_command) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3939 |             control_rc (plci, req, rc, ch, 0, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3940 |         } | 
 | 3941 |         else | 
 | 3942 |         { | 
 | 3943 |           if (plci->nl_global_req) | 
 | 3944 |           { | 
 | 3945 |             global_req = plci->nl_global_req; | 
 | 3946 |             plci->nl_global_req = 0; | 
 | 3947 |             if (rc != ASSIGN_OK) { | 
 | 3948 |               e->Id = 0; | 
 | 3949 |               if (plci->rx_dma_descriptor > 0) { | 
 | 3950 |                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1); | 
 | 3951 |                 plci->rx_dma_descriptor = 0; | 
 | 3952 |               } | 
 | 3953 |             } | 
 | 3954 |             channel_xmit_xon (plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3955 |             control_rc (plci, 0, rc, ch, global_req, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3956 |           } | 
 | 3957 |           else if (plci->data_sent) | 
 | 3958 |           { | 
 | 3959 |             channel_xmit_xon (plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3960 |             plci->data_sent = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3961 |             plci->NL.XNum = 1; | 
 | 3962 |             data_rc (plci, ch); | 
 | 3963 |             if (plci->internal_command) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3964 |               control_rc (plci, req, rc, ch, 0, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3965 |           } | 
 | 3966 |           else | 
 | 3967 |           { | 
 | 3968 |             channel_xmit_xon (plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3969 |             control_rc (plci, req, rc, ch, 0, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3970 |           } | 
 | 3971 |         } | 
 | 3972 |       } | 
 | 3973 |     } | 
 | 3974 |     else | 
 | 3975 |     { | 
 | 3976 |       /* | 
 | 3977 |          If REMOVE request was sent then we have to wait until | 
 | 3978 |          return code with Id set to zero arrives. | 
 | 3979 |          All other return codes should be ignored. | 
 | 3980 |          */ | 
 | 3981 |       if (req == REMOVE) | 
 | 3982 |       { | 
 | 3983 |         if (e->Id) | 
 | 3984 |         { | 
 | 3985 |           dbug(1,dprintf("cancel RC in REMOVE state")); | 
 | 3986 |           return; | 
 | 3987 |         } | 
 | 3988 |         plci->sig_remove_id = 0; | 
 | 3989 |       } | 
 | 3990 |       plci->sig_req = 0; | 
 | 3991 |       if (plci->sig_global_req) | 
 | 3992 |       { | 
 | 3993 |         global_req = plci->sig_global_req; | 
 | 3994 |         plci->sig_global_req = 0; | 
 | 3995 |         if (rc != ASSIGN_OK) | 
 | 3996 |           e->Id = 0; | 
 | 3997 |         channel_xmit_xon (plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 3998 |         control_rc (plci, 0, rc, ch, global_req, false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3999 |       } | 
 | 4000 |       else | 
 | 4001 |       { | 
 | 4002 |         channel_xmit_xon (plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 4003 |         control_rc (plci, req, rc, ch, 0, false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4004 |       } | 
 | 4005 |     } | 
 | 4006 |     /* | 
 | 4007 |       Again: in accordance with IDI spec Rc and Ind can't be delivered in the | 
 | 4008 |       same callback. Also if new XDI and protocol code used then jump | 
 | 4009 |       direct to finish. | 
 | 4010 |       */ | 
 | 4011 |     if (no_cancel_rc) { | 
 | 4012 |       channel_xmit_xon(plci); | 
 | 4013 |       goto capi_callback_suffix; | 
 | 4014 |     } | 
 | 4015 |   } | 
 | 4016 |  | 
 | 4017 |   channel_xmit_xon(plci); | 
 | 4018 |  | 
 | 4019 |   if (e->Ind) { | 
 | 4020 |     if (e->user[0] &0x8000) { | 
 | 4021 |       byte Ind = e->Ind & 0x0f; | 
 | 4022 |       byte Ch = e->IndCh; | 
 | 4023 |       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) && | 
 | 4024 |           (a->ch_flow_plci[Ch] == plci->Id)) { | 
 | 4025 |         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) { | 
 | 4026 |           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch)); | 
 | 4027 |         } | 
 | 4028 |         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK; | 
 | 4029 |       } | 
 | 4030 |       nl_ind(plci); | 
 | 4031 |       if ((e->RNR != 1) && | 
 | 4032 |           (a->ch_flow_plci[Ch] == plci->Id) && | 
 | 4033 |           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) { | 
 | 4034 |         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK; | 
 | 4035 |         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch)); | 
 | 4036 |       } | 
 | 4037 |     } else { | 
 | 4038 |       sig_ind(plci); | 
 | 4039 |     } | 
 | 4040 |     e->Ind = 0; | 
 | 4041 |   } | 
 | 4042 |  | 
 | 4043 | capi_callback_suffix: | 
 | 4044 |  | 
 | 4045 |   while (!plci->req_in | 
 | 4046 |    && !plci->internal_command | 
 | 4047 |    && (plci->msg_in_write_pos != plci->msg_in_read_pos)) | 
 | 4048 |   { | 
 | 4049 |     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos; | 
 | 4050 |  | 
 | 4051 |     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc; | 
 | 4052 |  | 
 | 4053 |     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]); | 
 | 4054 |     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i])); | 
 | 4055 |     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d", | 
 | 4056 |       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos)); | 
 | 4057 |     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos) | 
 | 4058 |     { | 
 | 4059 |       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | 
 | 4060 |       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD; | 
 | 4061 |     } | 
 | 4062 |     else | 
 | 4063 |     { | 
 | 4064 |       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD; | 
 | 4065 |     } | 
 | 4066 |     if (plci->msg_in_read_pos == plci->msg_in_write_pos) | 
 | 4067 |     { | 
 | 4068 |       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE; | 
 | 4069 |       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | 
 | 4070 |     } | 
 | 4071 |     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos) | 
 | 4072 |     { | 
 | 4073 |       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | 
 | 4074 |       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | 
 | 4075 |     } | 
 | 4076 |     i = api_put (appl, m); | 
 | 4077 |     if (i != 0) | 
 | 4078 |     { | 
 | 4079 |       if (m->header.command == _DATA_B3_R) | 
 | 4080 |  | 
| Andrew Morton | d3c8bdf | 2007-05-23 13:58:22 -0700 | [diff] [blame] | 4081 |         TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4082 |  | 
 | 4083 |       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command)); | 
 | 4084 |       break; | 
 | 4085 |     } | 
 | 4086 |  | 
 | 4087 |     if (plci->li_notify_update) | 
 | 4088 |     { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 4089 |       plci->li_notify_update = false; | 
 | 4090 |       mixer_notify_update (plci, false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4091 |     } | 
 | 4092 |  | 
 | 4093 |   } | 
 | 4094 |   send_data(plci); | 
 | 4095 |   send_req(plci); | 
 | 4096 | } | 
 | 4097 |  | 
 | 4098 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 4099 | static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req, | 
 | 4100 | 		       byte nl_rc) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4101 | { | 
 | 4102 |   dword Id; | 
 | 4103 |   dword rId; | 
 | 4104 |   word Number; | 
 | 4105 |   word Info=0; | 
 | 4106 |   word i; | 
 | 4107 |   word ncci; | 
 | 4108 |   DIVA_CAPI_ADAPTER   * a; | 
 | 4109 |   APPL   * appl; | 
 | 4110 |   PLCI   * rplci; | 
 | 4111 |     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00"; | 
 | 4112 |     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00"; | 
 | 4113 |  | 
 | 4114 |   if (!plci) { | 
 | 4115 |     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc)); | 
 | 4116 |     return; | 
 | 4117 |   } | 
 | 4118 |   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out)); | 
 | 4119 |   if(plci->req_in!=plci->req_out) | 
 | 4120 |   { | 
 | 4121 |     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK)) | 
 | 4122 |     { | 
 | 4123 |       dbug(1,dprintf("req_1return")); | 
 | 4124 |       return; | 
 | 4125 |     } | 
 | 4126 |     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */ | 
 | 4127 |   } | 
 | 4128 |   plci->req_in = plci->req_in_start = plci->req_out = 0; | 
 | 4129 |   dbug(1,dprintf("control_rc")); | 
 | 4130 |  | 
 | 4131 |   appl = plci->appl; | 
 | 4132 |   a = plci->adapter; | 
 | 4133 |   ncci = a->ch_ncci[ch]; | 
 | 4134 |   if(appl) | 
 | 4135 |   { | 
 | 4136 |     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id; | 
 | 4137 |     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER; | 
 | 4138 |     Number = plci->number; | 
 | 4139 |     dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command)); | 
 | 4140 |     dbug(1,dprintf("channels=0x%x",plci->channels)); | 
 | 4141 |     if (plci_remove_check(plci)) | 
 | 4142 |       return; | 
 | 4143 |     if(req==REMOVE && rc==ASSIGN_OK) | 
 | 4144 |     { | 
 | 4145 |       sig_req(plci,HANGUP,0); | 
 | 4146 |       sig_req(plci,REMOVE,0); | 
 | 4147 |       send_req(plci); | 
 | 4148 |     } | 
 | 4149 |     if(plci->command) | 
 | 4150 |     { | 
 | 4151 |       switch(plci->command) | 
 | 4152 |       { | 
 | 4153 |       case C_HOLD_REQ: | 
 | 4154 |         dbug(1,dprintf("HoldRC=0x%x",rc)); | 
 | 4155 |         SSparms[1] = (byte)S_HOLD; | 
 | 4156 |         if(rc!=OK) | 
 | 4157 |         { | 
 | 4158 |           plci->SuppState = IDLE; | 
 | 4159 |           Info = 0x2001; | 
 | 4160 |         } | 
 | 4161 |         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms); | 
 | 4162 |         break; | 
 | 4163 |  | 
 | 4164 |       case C_RETRIEVE_REQ: | 
 | 4165 |         dbug(1,dprintf("RetrieveRC=0x%x",rc)); | 
 | 4166 |         SSparms[1] = (byte)S_RETRIEVE; | 
 | 4167 |         if(rc!=OK) | 
 | 4168 |         { | 
 | 4169 |           plci->SuppState = CALL_HELD; | 
 | 4170 |           Info = 0x2001; | 
 | 4171 |         } | 
 | 4172 |         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms); | 
 | 4173 |         break; | 
 | 4174 |  | 
 | 4175 |       case _INFO_R: | 
 | 4176 |         dbug(1,dprintf("InfoRC=0x%x",rc)); | 
 | 4177 |         if(rc!=OK) Info=_WRONG_STATE; | 
 | 4178 |         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info); | 
 | 4179 |         break; | 
 | 4180 |  | 
 | 4181 |       case _CONNECT_R: | 
 | 4182 |         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc)); | 
 | 4183 |         if (plci->State == INC_DIS_PENDING) | 
 | 4184 |           break; | 
 | 4185 |         if(plci->Sig.Id!=0xff) | 
 | 4186 |         { | 
 | 4187 |           if (((global_req == ASSIGN) && (rc != ASSIGN_OK)) | 
 | 4188 |            || (!nl_rc && (req == CALL_REQ) && (rc != OK))) | 
 | 4189 |           { | 
 | 4190 |             dbug(1,dprintf("No more IDs/Call_Req failed")); | 
 | 4191 |             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI); | 
 | 4192 |             plci_remove(plci); | 
 | 4193 |             plci->State = IDLE; | 
 | 4194 |             break; | 
 | 4195 |           } | 
 | 4196 |           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING; | 
 | 4197 |           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0); | 
 | 4198 |         } | 
 | 4199 |         else /* D-ch activation */ | 
 | 4200 |         { | 
 | 4201 |           if (rc != ASSIGN_OK) | 
 | 4202 |           { | 
 | 4203 |             dbug(1,dprintf("No more IDs/X.25 Call_Req failed")); | 
 | 4204 |             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI); | 
 | 4205 |             plci_remove(plci); | 
 | 4206 |             plci->State = IDLE; | 
 | 4207 |             break; | 
 | 4208 |           } | 
 | 4209 |           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0); | 
 | 4210 |           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","",""); | 
 | 4211 |           plci->State = INC_ACT_PENDING; | 
 | 4212 |         } | 
 | 4213 |         break; | 
 | 4214 |  | 
 | 4215 |       case _CONNECT_I|RESPONSE: | 
 | 4216 |         if (plci->State != INC_DIS_PENDING) | 
 | 4217 |           plci->State = INC_CON_ACCEPT; | 
 | 4218 |         break; | 
 | 4219 |  | 
 | 4220 |       case _DISCONNECT_R: | 
 | 4221 |         if (plci->State == INC_DIS_PENDING) | 
 | 4222 |           break; | 
 | 4223 |         if(plci->Sig.Id!=0xff) | 
 | 4224 |         { | 
 | 4225 |           plci->State = OUTG_DIS_PENDING; | 
 | 4226 |           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0); | 
 | 4227 |         } | 
 | 4228 |         break; | 
 | 4229 |  | 
 | 4230 |       case SUSPEND_REQ: | 
 | 4231 |         break; | 
 | 4232 |  | 
 | 4233 |       case RESUME_REQ: | 
 | 4234 |         break; | 
 | 4235 |  | 
 | 4236 |       case _CONNECT_B3_R: | 
 | 4237 |         if(rc!=OK) | 
 | 4238 |         { | 
 | 4239 |           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER); | 
 | 4240 |           break; | 
 | 4241 |         } | 
 | 4242 |         ncci = get_ncci (plci, ch, 0); | 
 | 4243 |         Id = (Id & 0xffff) | (((dword) ncci) << 16); | 
 | 4244 |         plci->channels++; | 
 | 4245 |         if(req==N_RESET) | 
 | 4246 |         { | 
 | 4247 |           a->ncci_state[ncci] = INC_ACT_PENDING; | 
 | 4248 |           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0); | 
 | 4249 |           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | 
 | 4250 |         } | 
 | 4251 |         else | 
 | 4252 |         { | 
 | 4253 |           a->ncci_state[ncci] = OUTG_CON_PENDING; | 
 | 4254 |           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0); | 
 | 4255 |         } | 
 | 4256 |         break; | 
 | 4257 |  | 
 | 4258 |       case _CONNECT_B3_I|RESPONSE: | 
 | 4259 |         break; | 
 | 4260 |  | 
 | 4261 |       case _RESET_B3_R: | 
 | 4262 | /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/ | 
 | 4263 |         break; | 
 | 4264 |  | 
 | 4265 |       case _DISCONNECT_B3_R: | 
 | 4266 |         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0); | 
 | 4267 |         break; | 
 | 4268 |  | 
 | 4269 |       case _MANUFACTURER_R: | 
 | 4270 |         break; | 
 | 4271 |  | 
 | 4272 |       case PERM_LIST_REQ: | 
 | 4273 |         if(rc!=OK) | 
 | 4274 |         { | 
 | 4275 |           Info = _WRONG_IDENTIFIER; | 
 | 4276 |           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info); | 
 | 4277 |           plci_remove(plci); | 
 | 4278 |         } | 
 | 4279 |         else | 
 | 4280 |           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info); | 
 | 4281 |         break; | 
 | 4282 |  | 
 | 4283 |       default: | 
 | 4284 |         break; | 
 | 4285 |       } | 
 | 4286 |       plci->command = 0; | 
 | 4287 |     } | 
 | 4288 |     else if (plci->internal_command) | 
 | 4289 |     { | 
 | 4290 |       switch(plci->internal_command) | 
 | 4291 |       { | 
 | 4292 |       case BLOCK_PLCI: | 
 | 4293 |         return; | 
 | 4294 |  | 
 | 4295 |       case GET_MWI_STATE: | 
 | 4296 |         if(rc==OK) /* command supported, wait for indication */ | 
 | 4297 |         { | 
 | 4298 |           return; | 
 | 4299 |         } | 
 | 4300 |         plci_remove(plci); | 
 | 4301 |         break; | 
 | 4302 |  | 
 | 4303 |         /* Get Supported Services */ | 
 | 4304 |       case GETSERV_REQ_PEND: | 
 | 4305 |         if(rc==OK) /* command supported, wait for indication */ | 
 | 4306 |         { | 
 | 4307 |           break; | 
 | 4308 |         } | 
 | 4309 |         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); | 
 | 4310 |         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct); | 
 | 4311 |         plci_remove(plci); | 
 | 4312 |         break; | 
 | 4313 |  | 
 | 4314 |       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */ | 
 | 4315 |       case INTERR_NUMBERS_REQ_PEND: | 
 | 4316 |       case CF_START_PEND:                  /* Call Forwarding Start pending */ | 
 | 4317 |       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */ | 
 | 4318 |       case CCBS_REQUEST_REQ_PEND: | 
 | 4319 |       case CCBS_DEACTIVATE_REQ_PEND: | 
 | 4320 |       case CCBS_INTERROGATE_REQ_PEND: | 
 | 4321 |         switch(plci->internal_command) | 
 | 4322 |         { | 
 | 4323 |           case INTERR_DIVERSION_REQ_PEND: | 
 | 4324 |             SSparms[1] = S_INTERROGATE_DIVERSION; | 
 | 4325 |             break; | 
 | 4326 |           case INTERR_NUMBERS_REQ_PEND: | 
 | 4327 |             SSparms[1] = S_INTERROGATE_NUMBERS; | 
 | 4328 |             break; | 
 | 4329 |           case CF_START_PEND: | 
 | 4330 |             SSparms[1] = S_CALL_FORWARDING_START; | 
 | 4331 |             break; | 
 | 4332 |           case CF_STOP_PEND: | 
 | 4333 |             SSparms[1] = S_CALL_FORWARDING_STOP; | 
 | 4334 |             break; | 
 | 4335 |           case CCBS_REQUEST_REQ_PEND: | 
 | 4336 |             SSparms[1] = S_CCBS_REQUEST; | 
 | 4337 |             break; | 
 | 4338 |           case CCBS_DEACTIVATE_REQ_PEND: | 
 | 4339 |             SSparms[1] = S_CCBS_DEACTIVATE; | 
 | 4340 |             break; | 
 | 4341 |           case CCBS_INTERROGATE_REQ_PEND: | 
 | 4342 |             SSparms[1] = S_CCBS_INTERROGATE; | 
 | 4343 |             break; | 
 | 4344 |         } | 
 | 4345 |         if(global_req==ASSIGN) | 
 | 4346 |         { | 
 | 4347 |           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc)); | 
 | 4348 |           return; | 
 | 4349 |         } | 
 | 4350 |         if(!plci->appl) break; | 
 | 4351 |         if(rc==ISDN_GUARD_REJ) | 
 | 4352 |         { | 
 | 4353 |           Info = _CAPI_GUARD_ERROR; | 
 | 4354 |         } | 
 | 4355 |         else if(rc!=OK) | 
 | 4356 |         { | 
 | 4357 |           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED; | 
 | 4358 |         } | 
 | 4359 |         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7, | 
 | 4360 |               plci->number,"wws",Info,(word)3,SSparms); | 
 | 4361 |         if(Info) plci_remove(plci); | 
 | 4362 |         break; | 
 | 4363 |  | 
 | 4364 |         /* 3pty conference pending */ | 
 | 4365 |       case PTY_REQ_PEND: | 
 | 4366 |         if(!plci->relatedPTYPLCI) break; | 
 | 4367 |         rplci = plci->relatedPTYPLCI; | 
 | 4368 |         SSparms[1] = plci->ptyState; | 
 | 4369 |         rId = ((word)rplci->Id<<8)|rplci->adapter->Id; | 
 | 4370 |         if(rplci->tel) rId|=EXT_CONTROLLER; | 
 | 4371 |         if(rc!=OK) | 
 | 4372 |         { | 
 | 4373 |           Info = 0x300E; /* not supported */ | 
 | 4374 |           plci->relatedPTYPLCI = NULL; | 
 | 4375 |           plci->ptyState = 0; | 
 | 4376 |         } | 
 | 4377 |         sendf(rplci->appl, | 
 | 4378 |               _FACILITY_R|CONFIRM, | 
 | 4379 |               rId, | 
 | 4380 |               plci->number, | 
 | 4381 |               "wws",Info,(word)3,SSparms); | 
 | 4382 |         break; | 
 | 4383 |  | 
 | 4384 |         /* Explicit Call Transfer pending */ | 
 | 4385 |       case ECT_REQ_PEND: | 
 | 4386 |         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc)); | 
 | 4387 |         if(!plci->relatedPTYPLCI) break; | 
 | 4388 |         rplci = plci->relatedPTYPLCI; | 
 | 4389 |         SSparms[1] = S_ECT; | 
 | 4390 |         rId = ((word)rplci->Id<<8)|rplci->adapter->Id; | 
 | 4391 |         if(rplci->tel) rId|=EXT_CONTROLLER; | 
 | 4392 |         if(rc!=OK) | 
 | 4393 |         { | 
 | 4394 |           Info = 0x300E; /* not supported */ | 
 | 4395 |           plci->relatedPTYPLCI = NULL; | 
 | 4396 |           plci->ptyState = 0; | 
 | 4397 |         } | 
 | 4398 |         sendf(rplci->appl, | 
 | 4399 |               _FACILITY_R|CONFIRM, | 
 | 4400 |               rId, | 
 | 4401 |               plci->number, | 
 | 4402 |               "wws",Info,(word)3,SSparms); | 
 | 4403 |         break; | 
 | 4404 |  | 
 | 4405 |       case _MANUFACTURER_R: | 
 | 4406 |         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc)); | 
 | 4407 |         if ((global_req == ASSIGN) && (rc != ASSIGN_OK)) | 
 | 4408 |         { | 
 | 4409 |           dbug(1,dprintf("No more IDs")); | 
 | 4410 |           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI); | 
 | 4411 |           plci_remove(plci);  /* after codec init, internal codec commands pending */ | 
 | 4412 |         } | 
 | 4413 |         break; | 
 | 4414 |  | 
 | 4415 |       case _CONNECT_R: | 
 | 4416 |         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc)); | 
 | 4417 |         if ((global_req == ASSIGN) && (rc != ASSIGN_OK)) | 
 | 4418 |         { | 
 | 4419 |           dbug(1,dprintf("No more IDs")); | 
 | 4420 |           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI); | 
 | 4421 |           plci_remove(plci);  /* after codec init, internal codec commands pending */ | 
 | 4422 |         } | 
 | 4423 |         break; | 
 | 4424 |  | 
 | 4425 |       case PERM_COD_HOOK:                     /* finished with Hook_Ind */ | 
 | 4426 |         return; | 
 | 4427 |  | 
 | 4428 |       case PERM_COD_CALL: | 
 | 4429 |         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc)); | 
 | 4430 |         plci->internal_command = PERM_COD_CONN_PEND; | 
 | 4431 |         return; | 
 | 4432 |  | 
 | 4433 |       case PERM_COD_ASSIGN: | 
 | 4434 |         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc)); | 
 | 4435 |         if(rc!=ASSIGN_OK) break; | 
 | 4436 |         sig_req(plci,CALL_REQ,0); | 
 | 4437 |         send_req(plci); | 
 | 4438 |         plci->internal_command = PERM_COD_CALL; | 
 | 4439 |         return; | 
 | 4440 |  | 
 | 4441 |         /* Null Call Reference Request pending */ | 
 | 4442 |       case C_NCR_FAC_REQ: | 
 | 4443 |         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc)); | 
 | 4444 |         if(global_req==ASSIGN) | 
 | 4445 |         { | 
 | 4446 |           if(rc==ASSIGN_OK) | 
 | 4447 |           { | 
 | 4448 |             return; | 
 | 4449 |           } | 
 | 4450 |           else | 
 | 4451 |           { | 
 | 4452 |             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 4453 |             appl->NullCREnable = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4454 |             plci_remove(plci); | 
 | 4455 |           } | 
 | 4456 |         } | 
 | 4457 |         else if(req==NCR_FACILITY) | 
 | 4458 |         { | 
 | 4459 |           if(rc==OK) | 
 | 4460 |           { | 
 | 4461 |             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0); | 
 | 4462 |           } | 
 | 4463 |           else | 
 | 4464 |           { | 
 | 4465 |             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 4466 |             appl->NullCREnable = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4467 |           } | 
 | 4468 |           plci_remove(plci); | 
 | 4469 |         } | 
 | 4470 |         break; | 
 | 4471 |  | 
 | 4472 |       case HOOK_ON_REQ: | 
 | 4473 |         if(plci->channels) | 
 | 4474 |         { | 
 | 4475 |           if(a->ncci_state[ncci]==CONNECTED) | 
 | 4476 |           { | 
 | 4477 |             a->ncci_state[ncci] = OUTG_DIS_PENDING; | 
 | 4478 |             cleanup_ncci_data (plci, ncci); | 
 | 4479 |             nl_req_ncci(plci,N_DISC,(byte)ncci); | 
 | 4480 |           } | 
 | 4481 |           break; | 
 | 4482 |         } | 
 | 4483 |         break; | 
 | 4484 |  | 
 | 4485 |       case HOOK_OFF_REQ: | 
 | 4486 |         if (plci->State == INC_DIS_PENDING) | 
 | 4487 |           break; | 
 | 4488 |         sig_req(plci,CALL_REQ,0); | 
 | 4489 |         send_req(plci); | 
 | 4490 |         plci->State=OUTG_CON_PENDING; | 
 | 4491 |         break; | 
 | 4492 |  | 
 | 4493 |  | 
 | 4494 |       case MWI_ACTIVATE_REQ_PEND: | 
 | 4495 |       case MWI_DEACTIVATE_REQ_PEND: | 
 | 4496 |         if(global_req == ASSIGN && rc==ASSIGN_OK) | 
 | 4497 |         { | 
 | 4498 |           dbug(1,dprintf("MWI_REQ assigned")); | 
 | 4499 |           return; | 
 | 4500 |         } | 
 | 4501 |         else if(rc!=OK) | 
 | 4502 |         {                  | 
 | 4503 |           if(rc==WRONG_IE) | 
 | 4504 |           { | 
 | 4505 |             Info = 0x2007; /* Illegal message parameter coding */ | 
 | 4506 |             dbug(1,dprintf("MWI_REQ invalid parameter")); | 
 | 4507 |           } | 
 | 4508 |           else | 
 | 4509 |           { | 
 | 4510 |             Info = 0x300B; /* not supported */                       | 
 | 4511 |             dbug(1,dprintf("MWI_REQ not supported")); | 
 | 4512 |           } | 
 | 4513 |           /* 0x3010: Request not allowed in this state */ | 
 | 4514 |           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */ | 
 | 4515 |                      | 
 | 4516 |         } | 
 | 4517 |         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND) | 
 | 4518 |         { | 
 | 4519 |           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE); | 
 | 4520 |         } | 
 | 4521 |         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE); | 
 | 4522 |  | 
 | 4523 |         if(plci->cr_enquiry) | 
 | 4524 |         { | 
 | 4525 |           sendf(plci->appl, | 
 | 4526 |                 _FACILITY_R|CONFIRM, | 
 | 4527 |                 Id&0xf, | 
 | 4528 |                 plci->number, | 
 | 4529 |                 "wws",Info,(word)3,SSparms); | 
 | 4530 |           if(rc!=OK) plci_remove(plci); | 
 | 4531 |         } | 
 | 4532 |         else | 
 | 4533 |         { | 
 | 4534 |           sendf(plci->appl, | 
 | 4535 |                 _FACILITY_R|CONFIRM, | 
 | 4536 |                 Id, | 
 | 4537 |                 plci->number, | 
 | 4538 |                 "wws",Info,(word)3,SSparms); | 
 | 4539 |         } | 
 | 4540 |         break; | 
 | 4541 |  | 
 | 4542 |       case CONF_BEGIN_REQ_PEND: | 
 | 4543 |       case CONF_ADD_REQ_PEND: | 
 | 4544 |       case CONF_SPLIT_REQ_PEND: | 
 | 4545 |       case CONF_DROP_REQ_PEND: | 
 | 4546 |       case CONF_ISOLATE_REQ_PEND: | 
 | 4547 |       case CONF_REATTACH_REQ_PEND: | 
 | 4548 |         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc)); | 
 | 4549 |         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break; | 
 | 4550 |         rplci = plci; | 
 | 4551 |         rId = Id; | 
 | 4552 |         switch(plci->internal_command) | 
 | 4553 |         { | 
 | 4554 |           case CONF_BEGIN_REQ_PEND: | 
 | 4555 |             SSparms[1] = S_CONF_BEGIN; | 
 | 4556 |             break; | 
 | 4557 |           case CONF_ADD_REQ_PEND: | 
 | 4558 |             SSparms[1] = S_CONF_ADD; | 
 | 4559 |             rplci = plci->relatedPTYPLCI; | 
 | 4560 |             rId = ((word)rplci->Id<<8)|rplci->adapter->Id; | 
 | 4561 |             break; | 
 | 4562 |           case CONF_SPLIT_REQ_PEND: | 
 | 4563 |             SSparms[1] = S_CONF_SPLIT; | 
 | 4564 |             break; | 
 | 4565 |           case CONF_DROP_REQ_PEND: | 
 | 4566 |             SSparms[1] = S_CONF_DROP; | 
 | 4567 |             break; | 
 | 4568 |           case CONF_ISOLATE_REQ_PEND: | 
 | 4569 |             SSparms[1] = S_CONF_ISOLATE; | 
 | 4570 |             break; | 
 | 4571 |           case CONF_REATTACH_REQ_PEND: | 
 | 4572 |             SSparms[1] = S_CONF_REATTACH; | 
 | 4573 |             break; | 
 | 4574 |         } | 
 | 4575 |          | 
 | 4576 |         if(rc!=OK) | 
 | 4577 |         { | 
 | 4578 |           Info = 0x300E; /* not supported */ | 
 | 4579 |           plci->relatedPTYPLCI = NULL; | 
 | 4580 |           plci->ptyState = 0; | 
 | 4581 |         } | 
 | 4582 |         sendf(rplci->appl, | 
 | 4583 |               _FACILITY_R|CONFIRM, | 
 | 4584 |               rId, | 
 | 4585 |               plci->number, | 
 | 4586 |               "wws",Info,(word)3,SSparms); | 
 | 4587 |         break; | 
 | 4588 |  | 
 | 4589 |       case VSWITCH_REQ_PEND: | 
 | 4590 |         if(rc!=OK) | 
 | 4591 |         { | 
 | 4592 |           if(plci->relatedPTYPLCI) | 
 | 4593 |           { | 
 | 4594 |             plci->relatedPTYPLCI->vswitchstate=0; | 
 | 4595 |             plci->relatedPTYPLCI->vsprot=0; | 
 | 4596 |             plci->relatedPTYPLCI->vsprotdialect=0;     | 
 | 4597 |           } | 
 | 4598 |           plci->vswitchstate=0; | 
 | 4599 |           plci->vsprot=0; | 
 | 4600 |           plci->vsprotdialect=0; | 
 | 4601 |         } | 
 | 4602 |         else | 
 | 4603 |         { | 
 | 4604 |           if(plci->relatedPTYPLCI && | 
 | 4605 |              plci->vswitchstate==1 && | 
 | 4606 |              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */ | 
 | 4607 |             plci->vswitchstate=3; | 
 | 4608 |         } | 
 | 4609 |         break; | 
 | 4610 |  | 
 | 4611 |   /* Call Deflection Request pending (SSCT) */ | 
 | 4612 |       case CD_REQ_PEND: | 
 | 4613 |         SSparms[1] = S_CALL_DEFLECTION; | 
 | 4614 |         if(rc!=OK) | 
 | 4615 |         { | 
 | 4616 |           Info = 0x300E; /* not supported */ | 
 | 4617 |           plci->appl->CDEnable = 0; | 
 | 4618 |         }   | 
 | 4619 |         sendf(plci->appl,_FACILITY_R|CONFIRM,Id, | 
 | 4620 |           plci->number,"wws",Info,(word)3,SSparms); | 
 | 4621 |         break; | 
 | 4622 |  | 
 | 4623 |       case RTP_CONNECT_B3_REQ_COMMAND_2: | 
 | 4624 |         if (rc == OK) | 
 | 4625 |         { | 
 | 4626 |           ncci = get_ncci (plci, ch, 0); | 
 | 4627 |           Id = (Id & 0xffff) | (((dword) ncci) << 16); | 
 | 4628 |           plci->channels++; | 
 | 4629 |           a->ncci_state[ncci] = OUTG_CON_PENDING; | 
 | 4630 |         } | 
 | 4631 |  | 
 | 4632 |       default: | 
 | 4633 |         if (plci->internal_command_queue[0]) | 
 | 4634 |         { | 
 | 4635 |           (*(plci->internal_command_queue[0]))(Id, plci, rc); | 
 | 4636 |           if (plci->internal_command) | 
 | 4637 |             return; | 
 | 4638 |         } | 
 | 4639 |         break; | 
 | 4640 |       } | 
 | 4641 |       next_internal_command (Id, plci); | 
 | 4642 |     } | 
 | 4643 |   } | 
 | 4644 |   else /* appl==0 */ | 
 | 4645 |   { | 
 | 4646 |     Id = ((word)plci->Id<<8)|plci->adapter->Id; | 
 | 4647 |     if(plci->tel) Id|=EXT_CONTROLLER; | 
 | 4648 |  | 
 | 4649 |     switch(plci->internal_command) | 
 | 4650 |     { | 
 | 4651 |     case BLOCK_PLCI: | 
 | 4652 |       return; | 
 | 4653 |  | 
 | 4654 |     case START_L1_SIG_ASSIGN_PEND: | 
 | 4655 |     case REM_L1_SIG_ASSIGN_PEND: | 
 | 4656 |       if(global_req == ASSIGN) | 
 | 4657 |       { | 
 | 4658 |         break; | 
 | 4659 |       } | 
 | 4660 |       else | 
 | 4661 |       { | 
 | 4662 |         dbug(1,dprintf("***L1 Req rem PLCI")); | 
 | 4663 |         plci->internal_command = 0; | 
 | 4664 |         sig_req(plci,REMOVE,0); | 
 | 4665 |         send_req(plci); | 
 | 4666 |       } | 
 | 4667 |       break; | 
 | 4668 |  | 
 | 4669 |       /* Call Deflection Request pending, just no appl ptr assigned */ | 
 | 4670 |     case CD_REQ_PEND: | 
 | 4671 |       SSparms[1] = S_CALL_DEFLECTION; | 
 | 4672 |       if(rc!=OK) | 
 | 4673 |       { | 
 | 4674 |         Info = 0x300E; /* not supported */ | 
 | 4675 |       } | 
 | 4676 |       for(i=0; i<max_appl; i++) | 
 | 4677 |       { | 
 | 4678 |         if(application[i].CDEnable) | 
 | 4679 |         { | 
 | 4680 |           if(!application[i].Id) application[i].CDEnable = 0; | 
 | 4681 |           else | 
 | 4682 |           { | 
 | 4683 |             sendf(&application[i],_FACILITY_R|CONFIRM,Id, | 
 | 4684 |                   plci->number,"wws",Info,(word)3,SSparms); | 
 | 4685 |             if(Info) application[i].CDEnable = 0; | 
 | 4686 |           } | 
 | 4687 |         } | 
 | 4688 |       } | 
 | 4689 |       plci->internal_command = 0; | 
 | 4690 |       break; | 
 | 4691 |  | 
 | 4692 |     case PERM_COD_HOOK:                   /* finished with Hook_Ind */ | 
 | 4693 |       return; | 
 | 4694 |  | 
 | 4695 |     case PERM_COD_CALL: | 
 | 4696 |       plci->internal_command = PERM_COD_CONN_PEND; | 
 | 4697 |       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc)); | 
 | 4698 |       return; | 
 | 4699 |  | 
 | 4700 |     case PERM_COD_ASSIGN: | 
 | 4701 |       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc)); | 
 | 4702 |       plci->internal_command = 0; | 
 | 4703 |       if(rc!=ASSIGN_OK) break; | 
 | 4704 |       plci->internal_command = PERM_COD_CALL; | 
 | 4705 |       sig_req(plci,CALL_REQ,0); | 
 | 4706 |       send_req(plci); | 
 | 4707 |       return; | 
 | 4708 |  | 
 | 4709 |     case LISTEN_SIG_ASSIGN_PEND: | 
 | 4710 |       if(rc == ASSIGN_OK) | 
 | 4711 |       { | 
 | 4712 |         plci->internal_command = 0; | 
 | 4713 |         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id)); | 
 | 4714 |         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */ | 
 | 4715 |         sig_req(plci,INDICATE_REQ,0); | 
 | 4716 |         send_req(plci); | 
 | 4717 |       } | 
 | 4718 |       else | 
 | 4719 |       { | 
 | 4720 |         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc)); | 
 | 4721 |         a->listen_active--; | 
 | 4722 |         plci_remove(plci); | 
 | 4723 |         plci->State = IDLE; | 
 | 4724 |       } | 
 | 4725 |       break; | 
 | 4726 |  | 
 | 4727 |     case USELAW_REQ: | 
 | 4728 |       if(global_req == ASSIGN) | 
 | 4729 |       { | 
 | 4730 |         if (rc==ASSIGN_OK) | 
 | 4731 |       { | 
 | 4732 |         sig_req(plci,LAW_REQ,0); | 
 | 4733 |         send_req(plci); | 
 | 4734 |         dbug(1,dprintf("Auto-Law assigned")); | 
 | 4735 |         } | 
 | 4736 |         else | 
 | 4737 |         { | 
 | 4738 |           dbug(1,dprintf("Auto-Law assign failed")); | 
 | 4739 |           a->automatic_law = 3; | 
 | 4740 |           plci->internal_command = 0; | 
 | 4741 |           a->automatic_lawPLCI = NULL; | 
 | 4742 |         } | 
 | 4743 |         break; | 
 | 4744 |       } | 
 | 4745 |       else if(req == LAW_REQ && rc==OK) | 
 | 4746 |       { | 
 | 4747 |         dbug(1,dprintf("Auto-Law initiated")); | 
 | 4748 |         a->automatic_law = 2; | 
 | 4749 |         plci->internal_command = 0; | 
 | 4750 |       } | 
 | 4751 |       else | 
 | 4752 |       { | 
 | 4753 |         dbug(1,dprintf("Auto-Law not supported")); | 
 | 4754 |         a->automatic_law = 3; | 
 | 4755 |         plci->internal_command = 0; | 
 | 4756 |         sig_req(plci,REMOVE,0); | 
 | 4757 |         send_req(plci); | 
 | 4758 |         a->automatic_lawPLCI = NULL; | 
 | 4759 |       } | 
 | 4760 |       break; | 
 | 4761 |     } | 
 | 4762 |     plci_remove_check(plci); | 
 | 4763 |   } | 
 | 4764 | } | 
 | 4765 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 4766 | static void data_rc(PLCI *plci, byte ch) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4767 | { | 
 | 4768 |   dword Id; | 
 | 4769 |   DIVA_CAPI_ADAPTER   * a; | 
 | 4770 |   NCCI   *ncci_ptr; | 
 | 4771 |   DATA_B3_DESC   *data; | 
 | 4772 |   word ncci; | 
 | 4773 |  | 
 | 4774 |   if (plci->appl) | 
 | 4775 |   { | 
 | 4776 |     TransmitBufferFree (plci->appl, plci->data_sent_ptr); | 
 | 4777 |     a = plci->adapter; | 
 | 4778 |     ncci = a->ch_ncci[ch]; | 
 | 4779 |     if (ncci && (a->ncci_plci[ncci] == plci->Id)) | 
 | 4780 |     { | 
 | 4781 |       ncci_ptr = &(a->ncci[ncci]); | 
 | 4782 |       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending)); | 
 | 4783 |       if (ncci_ptr->data_pending) | 
 | 4784 |       { | 
 | 4785 |         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]); | 
 | 4786 |         if (!(data->Flags &4) && a->ncci_state[ncci]) | 
 | 4787 |         { | 
 | 4788 |           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id; | 
 | 4789 |           if(plci->tel) Id|=EXT_CONTROLLER; | 
 | 4790 |           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number, | 
 | 4791 |                 "ww",data->Handle,0); | 
 | 4792 |         } | 
 | 4793 |         (ncci_ptr->data_out)++; | 
 | 4794 |         if (ncci_ptr->data_out == MAX_DATA_B3) | 
 | 4795 |           ncci_ptr->data_out = 0; | 
 | 4796 |         (ncci_ptr->data_pending)--; | 
 | 4797 |       } | 
 | 4798 |     } | 
 | 4799 |   } | 
 | 4800 | } | 
 | 4801 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 4802 | static void data_ack(PLCI *plci, byte ch) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4803 | { | 
 | 4804 |   dword Id; | 
 | 4805 |   DIVA_CAPI_ADAPTER   * a; | 
 | 4806 |   NCCI   *ncci_ptr; | 
 | 4807 |   word ncci; | 
 | 4808 |  | 
 | 4809 |   a = plci->adapter; | 
 | 4810 |   ncci = a->ch_ncci[ch]; | 
 | 4811 |   ncci_ptr = &(a->ncci[ncci]); | 
 | 4812 |   if (ncci_ptr->data_ack_pending) | 
 | 4813 |   { | 
 | 4814 |     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id)) | 
 | 4815 |     { | 
 | 4816 |       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id; | 
 | 4817 |       if(plci->tel) Id|=EXT_CONTROLLER; | 
 | 4818 |       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number, | 
 | 4819 |             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0); | 
 | 4820 |     } | 
 | 4821 |     (ncci_ptr->data_ack_out)++; | 
 | 4822 |     if (ncci_ptr->data_ack_out == MAX_DATA_ACK) | 
 | 4823 |       ncci_ptr->data_ack_out = 0; | 
 | 4824 |     (ncci_ptr->data_ack_pending)--; | 
 | 4825 |   } | 
 | 4826 | } | 
 | 4827 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 4828 | static void sig_ind(PLCI *plci) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4829 | { | 
 | 4830 |   dword x_Id; | 
 | 4831 |   dword Id; | 
 | 4832 |   dword rId; | 
 | 4833 |   word Number = 0; | 
 | 4834 |   word i; | 
 | 4835 |   word cip; | 
 | 4836 |   dword cip_mask; | 
 | 4837 |   byte   *ie; | 
 | 4838 |   DIVA_CAPI_ADAPTER   * a; | 
 | 4839 |     API_PARSE saved_parms[MAX_MSG_PARMS+1]; | 
 | 4840 | #define MAXPARMSIDS 31 | 
 | 4841 |     byte   * parms[MAXPARMSIDS]; | 
 | 4842 |     byte   * add_i[4]; | 
 | 4843 |     byte   * multi_fac_parms[MAX_MULTI_IE]; | 
 | 4844 |     byte   * multi_pi_parms [MAX_MULTI_IE]; | 
 | 4845 |     byte   * multi_ssext_parms [MAX_MULTI_IE]; | 
 | 4846 |     byte   * multi_CiPN_parms [MAX_MULTI_IE]; | 
 | 4847 |  | 
 | 4848 |     byte   * multi_vswitch_parms [MAX_MULTI_IE]; | 
 | 4849 |  | 
 | 4850 |   byte ai_len; | 
 | 4851 |     byte   *esc_chi = ""; | 
 | 4852 |     byte   *esc_law = ""; | 
 | 4853 |     byte   *pty_cai = ""; | 
 | 4854 |     byte   *esc_cr  = ""; | 
 | 4855 |     byte   *esc_profile = ""; | 
 | 4856 |  | 
 | 4857 |     byte facility[256]; | 
 | 4858 |   PLCI   * tplci = NULL; | 
 | 4859 |   byte chi[] = "\x02\x18\x01"; | 
 | 4860 |   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08"; | 
 | 4861 |     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00"; | 
 | 4862 |   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */ | 
 | 4863 |   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */ | 
 | 4864 |   /* SMSG is situated at the end because its 0 (for compatibility reasons */ | 
 | 4865 |   /* (see Info_Mask Bit 4, first IE. then the message type)           */ | 
 | 4866 |     word parms_id[] = | 
 | 4867 |          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA, | 
 | 4868 |           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW, | 
 | 4869 |           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR, | 
 | 4870 |           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG}; | 
 | 4871 |           /* 14 FTY repl by ESC_CHI */ | 
 | 4872 |           /* 18 PI  repl by ESC_LAW */ | 
 | 4873 |          /* removed OAD changed to 0xff for future use, OAD is multiIE now */ | 
 | 4874 |      word multi_fac_id[] = {1, FTY}; | 
 | 4875 |      word multi_pi_id[]  = {1, PI}; | 
 | 4876 |      word multi_CiPN_id[]  = {1, OAD}; | 
 | 4877 |      word multi_ssext_id[]  = {1, ESC_SSEXT}; | 
 | 4878 |  | 
 | 4879 |      word multi_vswitch_id[]  = {1, ESC_VSWITCH}; | 
 | 4880 |  | 
 | 4881 |   byte   * cau; | 
 | 4882 |   word ncci; | 
 | 4883 |     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/ | 
 | 4884 |     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00"; | 
 | 4885 |     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; | 
 | 4886 |     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00"; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 4887 |   byte force_mt_info = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4888 |   byte dir; | 
 | 4889 |   dword d; | 
 | 4890 |   word w; | 
 | 4891 |  | 
 | 4892 |   a = plci->adapter; | 
 | 4893 |   Id = ((word)plci->Id<<8)|a->Id; | 
 | 4894 |   PUT_WORD(&SS_Ind[4],0x0000); | 
 | 4895 |  | 
 | 4896 |   if (plci->sig_remove_id) | 
 | 4897 |   { | 
 | 4898 |     plci->Sig.RNR = 2; /* discard */ | 
 | 4899 |     dbug(1,dprintf("SIG discard while remove pending")); | 
 | 4900 |     return; | 
 | 4901 |   } | 
 | 4902 |   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER; | 
 | 4903 |   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d", | 
 | 4904 |     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer)); | 
 | 4905 |   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels) | 
 | 4906 |   { | 
 | 4907 |     plci->Sig.RNR = 1; | 
 | 4908 |     return; | 
 | 4909 |   } | 
 | 4910 |   if(plci->Sig.Ind==HANGUP && plci->channels) | 
 | 4911 |   { | 
 | 4912 |     plci->Sig.RNR = 1; | 
 | 4913 |     plci->hangup_flow_ctrl_timer++; | 
 | 4914 |     /* recover the network layer after timeout */ | 
 | 4915 |     if(plci->hangup_flow_ctrl_timer==100) | 
 | 4916 |     { | 
 | 4917 |       dbug(1,dprintf("Exceptional disc")); | 
 | 4918 |       plci->Sig.RNR = 0; | 
 | 4919 |       plci->hangup_flow_ctrl_timer = 0; | 
 | 4920 |       for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | 
 | 4921 |       { | 
 | 4922 |         if (a->ncci_plci[ncci] == plci->Id) | 
 | 4923 |         { | 
 | 4924 |           cleanup_ncci_data (plci, ncci); | 
 | 4925 |           if(plci->channels)plci->channels--; | 
 | 4926 |           if (plci->appl) | 
 | 4927 |             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,""); | 
 | 4928 |         } | 
 | 4929 |       } | 
 | 4930 |       if (plci->appl) | 
 | 4931 |         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0); | 
 | 4932 |       plci_remove(plci); | 
 | 4933 |       plci->State=IDLE; | 
 | 4934 |     } | 
 | 4935 |     return; | 
 | 4936 |   } | 
 | 4937 |  | 
 | 4938 |   /* do first parse the info with no OAD in, because OAD will be converted */ | 
 | 4939 |   /* first the multiple facility IE, then mult. progress ind.              */ | 
 | 4940 |   /* then the parameters for the info_ind + conn_ind                       */ | 
 | 4941 |   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE); | 
 | 4942 |   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE); | 
 | 4943 |   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE); | 
 | 4944 |  | 
 | 4945 |   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE); | 
 | 4946 |  | 
 | 4947 |   IndParse(plci,parms_id,parms,0); | 
 | 4948 |   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE); | 
 | 4949 |   esc_chi  = parms[14]; | 
 | 4950 |   esc_law  = parms[18]; | 
 | 4951 |   pty_cai  = parms[24]; | 
 | 4952 |   esc_cr   = parms[25]; | 
 | 4953 |   esc_profile = parms[27]; | 
 | 4954 |   if(esc_cr[0] && plci) | 
 | 4955 |   { | 
 | 4956 |     if(plci->cr_enquiry && plci->appl) | 
 | 4957 |     { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 4958 |       plci->cr_enquiry = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4959 |       /* d = MANU_ID            */ | 
 | 4960 |       /* w = m_command          */ | 
 | 4961 |       /* b = total length       */ | 
 | 4962 |       /* b = indication type    */ | 
 | 4963 |       /* b = length of all IEs  */ | 
 | 4964 |       /* b = IE1                */ | 
 | 4965 |       /* S = IE1 length + cont. */ | 
 | 4966 |       /* b = IE2                */ | 
| Paulius Zaleckas | efad798b | 2008-02-03 15:42:53 +0200 | [diff] [blame] | 4967 |       /* S = IE2 length + cont. */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4968 |       sendf(plci->appl, | 
 | 4969 |         _MANUFACTURER_I, | 
 | 4970 |         Id, | 
 | 4971 |         0, | 
 | 4972 |         "dwbbbbSbS",_DI_MANU_ID,plci->m_command, | 
 | 4973 |         2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law); | 
 | 4974 |     } | 
 | 4975 |   } | 
 | 4976 |   /* create the additional info structure                                  */ | 
 | 4977 |   add_i[1] = parms[15]; /* KEY of additional info */ | 
 | 4978 |   add_i[2] = parms[11]; /* UUI of additional info */ | 
 | 4979 |   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility); | 
 | 4980 |  | 
 | 4981 |   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */ | 
 | 4982 |   /* indication returns by the card if requested by the function           */ | 
 | 4983 |   /* AutomaticLaw() after driver init                                      */ | 
 | 4984 |   if (a->automatic_law<4) | 
 | 4985 |   { | 
 | 4986 |     if(esc_law[0]){ | 
 | 4987 |       if(esc_law[2]){ | 
 | 4988 |         dbug(0,dprintf("u-Law selected")); | 
 | 4989 |         a->u_law = 1; | 
 | 4990 |       } | 
 | 4991 |       else { | 
 | 4992 |         dbug(0,dprintf("a-Law selected")); | 
 | 4993 |         a->u_law = 0; | 
 | 4994 |       } | 
 | 4995 |       a->automatic_law = 4; | 
 | 4996 |       if(plci==a->automatic_lawPLCI) { | 
 | 4997 |         plci->internal_command = 0; | 
 | 4998 |         sig_req(plci,REMOVE,0); | 
 | 4999 |         send_req(plci); | 
 | 5000 |         a->automatic_lawPLCI = NULL; | 
 | 5001 |       } | 
 | 5002 |     } | 
 | 5003 |     if (esc_profile[0]) | 
 | 5004 |     { | 
 | 5005 |       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx", | 
 | 5006 |         UnMapController (a->Id), GET_DWORD (&esc_profile[6]), | 
 | 5007 |         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]), | 
 | 5008 |         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46]))); | 
 | 5009 |  | 
 | 5010 |       a->profile.Global_Options &= 0x000000ffL; | 
 | 5011 |       a->profile.B1_Protocols &= 0x000003ffL; | 
 | 5012 |       a->profile.B2_Protocols &= 0x00001fdfL; | 
 | 5013 |       a->profile.B3_Protocols &= 0x000000b7L; | 
 | 5014 |  | 
 | 5015 |       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) | | 
 | 5016 |         GL_BCHANNEL_OPERATION_SUPPORTED; | 
 | 5017 |       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]); | 
 | 5018 |       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]); | 
 | 5019 |       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]); | 
 | 5020 |       a->manufacturer_features = GET_DWORD (&esc_profile[46]); | 
 | 5021 |       a->man_profile.private_options = 0; | 
 | 5022 |  | 
 | 5023 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER) | 
 | 5024 |       { | 
 | 5025 |         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER; | 
 | 5026 |         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED; | 
 | 5027 |       } | 
 | 5028 |  | 
 | 5029 |  | 
 | 5030 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP) | 
 | 5031 |         a->man_profile.private_options |= 1L << PRIVATE_RTP; | 
 | 5032 |       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]); | 
 | 5033 |       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]); | 
 | 5034 |  | 
 | 5035 |  | 
 | 5036 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38) | 
 | 5037 |         a->man_profile.private_options |= 1L << PRIVATE_T38; | 
 | 5038 |  | 
 | 5039 |  | 
 | 5040 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD) | 
 | 5041 |         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD; | 
 | 5042 |  | 
 | 5043 |  | 
 | 5044 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18) | 
 | 5045 |         a->man_profile.private_options |= 1L << PRIVATE_V18; | 
 | 5046 |  | 
 | 5047 |  | 
 | 5048 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE) | 
 | 5049 |         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE; | 
 | 5050 |  | 
 | 5051 |  | 
 | 5052 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS) | 
 | 5053 |         a->man_profile.private_options |= 1L << PRIVATE_PIAFS; | 
 | 5054 |  | 
 | 5055 |  | 
 | 5056 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | 
 | 5057 |         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS; | 
 | 5058 |  | 
 | 5059 |  | 
 | 5060 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN) | 
 | 5061 |         a->man_profile.private_options |= 1L << PRIVATE_VOWN; | 
 | 5062 |  | 
 | 5063 |  | 
 | 5064 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD) | 
 | 5065 |         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD; | 
 | 5066 |  | 
 | 5067 |     } | 
 | 5068 |     else | 
 | 5069 |     { | 
 | 5070 |       a->profile.Global_Options &= 0x0000007fL; | 
 | 5071 |       a->profile.B1_Protocols &= 0x000003dfL; | 
 | 5072 |       a->profile.B2_Protocols &= 0x00001adfL; | 
 | 5073 |       a->profile.B3_Protocols &= 0x000000b7L; | 
 | 5074 |       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF; | 
 | 5075 |     } | 
 | 5076 |     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF | | 
 | 5077 |       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)) | 
 | 5078 |     { | 
 | 5079 |       a->profile.Global_Options |= GL_DTMF_SUPPORTED; | 
 | 5080 |     } | 
 | 5081 |     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL; | 
 | 5082 |     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx", | 
 | 5083 |       UnMapController (a->Id), a->profile.Global_Options, | 
 | 5084 |       a->profile.B1_Protocols, a->profile.B2_Protocols, | 
 | 5085 |       a->profile.B3_Protocols, a->manufacturer_features)); | 
 | 5086 |   } | 
 | 5087 |   /* codec plci for the handset/hook state support is just an internal id  */ | 
 | 5088 |   if(plci!=a->AdvCodecPLCI) | 
 | 5089 |   { | 
 | 5090 |     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0); | 
 | 5091 |     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0); | 
 | 5092 |     SendSSExtInd(NULL,plci,Id,multi_ssext_parms); | 
 | 5093 |     SendInfo(plci,Id, parms, force_mt_info); | 
 | 5094 |  | 
 | 5095 |     VSwitchReqInd(plci,Id,multi_vswitch_parms); | 
 | 5096 |  | 
 | 5097 |   } | 
 | 5098 |  | 
 | 5099 |   /* switch the codec to the b-channel                                     */ | 
 | 5100 |   if(esc_chi[0] && plci && !plci->SuppState){ | 
 | 5101 |     plci->b_channel = esc_chi[esc_chi[0]]&0x1f; | 
 | 5102 |     mixer_set_bchannel_id_esc (plci, plci->b_channel); | 
 | 5103 |     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel)); | 
 | 5104 |     if(plci->tel==ADV_VOICE && plci->appl) { | 
 | 5105 |       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a); | 
 | 5106 |     } | 
 | 5107 |   } | 
 | 5108 |  | 
 | 5109 |   if(plci->appl) Number = plci->appl->Number++; | 
 | 5110 |  | 
 | 5111 |   switch(plci->Sig.Ind) { | 
 | 5112 |   /* Response to Get_Supported_Services request */ | 
 | 5113 |   case S_SUPPORTED: | 
 | 5114 |     dbug(1,dprintf("S_Supported")); | 
 | 5115 |     if(!plci->appl) break; | 
 | 5116 |     if(pty_cai[0]==4) | 
 | 5117 |     { | 
 | 5118 |       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) ); | 
 | 5119 |     } | 
 | 5120 |     else | 
 | 5121 |     { | 
 | 5122 |       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE); | 
 | 5123 |     } | 
 | 5124 |     PUT_WORD (&CF_Ind[1], 0); | 
 | 5125 |     PUT_WORD (&CF_Ind[4], 0); | 
 | 5126 |     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind); | 
 | 5127 |     plci_remove(plci); | 
 | 5128 |     break; | 
 | 5129 |                      | 
 | 5130 |   /* Supplementary Service rejected */ | 
 | 5131 |   case S_SERVICE_REJ: | 
 | 5132 |     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5])); | 
 | 5133 |     if(!pty_cai[0]) break; | 
 | 5134 |     switch (pty_cai[5]) | 
 | 5135 |     { | 
 | 5136 |     case ECT_EXECUTE: | 
 | 5137 |     case THREE_PTY_END: | 
 | 5138 |     case THREE_PTY_BEGIN: | 
 | 5139 |       if(!plci->relatedPTYPLCI) break; | 
 | 5140 |       tplci = plci->relatedPTYPLCI; | 
 | 5141 |       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id; | 
 | 5142 |       if(tplci->tel) rId|=EXT_CONTROLLER; | 
 | 5143 |       if(pty_cai[5]==ECT_EXECUTE) | 
 | 5144 |       { | 
 | 5145 |         PUT_WORD(&SS_Ind[1],S_ECT); | 
 | 5146 |  | 
 | 5147 |         plci->vswitchstate=0; | 
 | 5148 |         plci->relatedPTYPLCI->vswitchstate=0; | 
 | 5149 |  | 
 | 5150 |       } | 
 | 5151 |       else | 
 | 5152 |       { | 
 | 5153 |         PUT_WORD(&SS_Ind[1],pty_cai[5]+3); | 
 | 5154 |       } | 
 | 5155 |       if(pty_cai[2]!=0xff) | 
 | 5156 |       { | 
 | 5157 |         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); | 
 | 5158 |       } | 
 | 5159 |       else | 
 | 5160 |       { | 
 | 5161 |         PUT_WORD(&SS_Ind[4],0x300E); | 
 | 5162 |       } | 
 | 5163 |       plci->relatedPTYPLCI = NULL; | 
 | 5164 |       plci->ptyState = 0; | 
 | 5165 |       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind); | 
 | 5166 |       break; | 
 | 5167 |  | 
 | 5168 |     case CALL_DEFLECTION: | 
 | 5169 |       if(pty_cai[2]!=0xff) | 
 | 5170 |       { | 
 | 5171 |         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); | 
 | 5172 |       } | 
 | 5173 |       else | 
 | 5174 |       { | 
 | 5175 |         PUT_WORD(&SS_Ind[4],0x300E); | 
 | 5176 |       } | 
 | 5177 |       PUT_WORD(&SS_Ind[1],pty_cai[5]); | 
 | 5178 |       for(i=0; i<max_appl; i++) | 
 | 5179 |       { | 
 | 5180 |         if(application[i].CDEnable) | 
 | 5181 |         { | 
 | 5182 |           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 5183 |           application[i].CDEnable = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5184 |         } | 
 | 5185 |       } | 
 | 5186 |       break; | 
 | 5187 |  | 
 | 5188 |     case DEACTIVATION_DIVERSION: | 
 | 5189 |     case ACTIVATION_DIVERSION: | 
 | 5190 |     case DIVERSION_INTERROGATE_CFU: | 
 | 5191 |     case DIVERSION_INTERROGATE_CFB: | 
 | 5192 |     case DIVERSION_INTERROGATE_CFNR: | 
 | 5193 |     case DIVERSION_INTERROGATE_NUM: | 
 | 5194 |     case CCBS_REQUEST: | 
 | 5195 |     case CCBS_DEACTIVATE: | 
 | 5196 |     case CCBS_INTERROGATE: | 
 | 5197 |       if(!plci->appl) break; | 
 | 5198 |       if(pty_cai[2]!=0xff) | 
 | 5199 |       { | 
 | 5200 |         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]); | 
 | 5201 |       } | 
 | 5202 |       else | 
 | 5203 |       { | 
 | 5204 |         PUT_WORD(&Interr_Err_Ind[4],0x300E); | 
 | 5205 |       } | 
 | 5206 |       switch (pty_cai[5]) | 
 | 5207 |       { | 
 | 5208 |         case DEACTIVATION_DIVERSION: | 
 | 5209 |           dbug(1,dprintf("Deact_Div")); | 
 | 5210 |           Interr_Err_Ind[0]=0x9; | 
 | 5211 |           Interr_Err_Ind[3]=0x6; | 
 | 5212 |           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP); | 
 | 5213 |           break; | 
 | 5214 |         case ACTIVATION_DIVERSION: | 
 | 5215 |           dbug(1,dprintf("Act_Div")); | 
 | 5216 |           Interr_Err_Ind[0]=0x9; | 
 | 5217 |           Interr_Err_Ind[3]=0x6; | 
 | 5218 |           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START); | 
 | 5219 |           break; | 
 | 5220 |         case DIVERSION_INTERROGATE_CFU: | 
 | 5221 |         case DIVERSION_INTERROGATE_CFB: | 
 | 5222 |         case DIVERSION_INTERROGATE_CFNR: | 
 | 5223 |           dbug(1,dprintf("Interr_Div")); | 
 | 5224 |           Interr_Err_Ind[0]=0xa; | 
 | 5225 |           Interr_Err_Ind[3]=0x7; | 
 | 5226 |           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION); | 
 | 5227 |           break; | 
 | 5228 |         case DIVERSION_INTERROGATE_NUM: | 
 | 5229 |           dbug(1,dprintf("Interr_Num")); | 
 | 5230 |           Interr_Err_Ind[0]=0xa; | 
 | 5231 |           Interr_Err_Ind[3]=0x7; | 
 | 5232 |           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS); | 
 | 5233 |           break; | 
 | 5234 |         case CCBS_REQUEST: | 
 | 5235 |           dbug(1,dprintf("CCBS Request")); | 
 | 5236 |           Interr_Err_Ind[0]=0xd; | 
 | 5237 |           Interr_Err_Ind[3]=0xa; | 
 | 5238 |           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST); | 
 | 5239 |           break; | 
 | 5240 |         case CCBS_DEACTIVATE: | 
 | 5241 |           dbug(1,dprintf("CCBS Deactivate")); | 
 | 5242 |           Interr_Err_Ind[0]=0x9; | 
 | 5243 |           Interr_Err_Ind[3]=0x6; | 
 | 5244 |           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE); | 
 | 5245 |           break; | 
 | 5246 |         case CCBS_INTERROGATE: | 
 | 5247 |           dbug(1,dprintf("CCBS Interrogate")); | 
 | 5248 |           Interr_Err_Ind[0]=0xb; | 
 | 5249 |           Interr_Err_Ind[3]=0x8; | 
 | 5250 |           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE); | 
 | 5251 |           break; | 
 | 5252 |       } | 
 | 5253 |       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle); | 
 | 5254 |       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind); | 
 | 5255 |       plci_remove(plci); | 
 | 5256 |       break; | 
 | 5257 |     case ACTIVATION_MWI:       | 
 | 5258 |     case DEACTIVATION_MWI: | 
 | 5259 |       if(pty_cai[5]==ACTIVATION_MWI) | 
 | 5260 |       { | 
 | 5261 |         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE); | 
 | 5262 |       } | 
 | 5263 |       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); | 
 | 5264 |        | 
 | 5265 |       if(pty_cai[2]!=0xff) | 
 | 5266 |       { | 
 | 5267 |         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); | 
 | 5268 |       } | 
 | 5269 |       else | 
 | 5270 |       { | 
 | 5271 |         PUT_WORD(&SS_Ind[4],0x300E); | 
 | 5272 |       } | 
 | 5273 |  | 
 | 5274 |       if(plci->cr_enquiry) | 
 | 5275 |       { | 
 | 5276 |         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind); | 
 | 5277 |         plci_remove(plci); | 
 | 5278 |       } | 
 | 5279 |       else | 
 | 5280 |       { | 
 | 5281 |         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | 
 | 5282 |       } | 
 | 5283 |       break; | 
 | 5284 |     case CONF_ADD: /* ERROR */ | 
 | 5285 |     case CONF_BEGIN: | 
 | 5286 |     case CONF_DROP: | 
 | 5287 |     case CONF_ISOLATE: | 
 | 5288 |     case CONF_REATTACH: | 
 | 5289 |       CONF_Ind[0]=9; | 
 | 5290 |       CONF_Ind[3]=6;    | 
 | 5291 |       switch(pty_cai[5]) | 
 | 5292 |       { | 
 | 5293 |       case CONF_BEGIN: | 
 | 5294 |           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN); | 
 | 5295 |           plci->ptyState = 0; | 
 | 5296 |           break; | 
 | 5297 |       case CONF_DROP: | 
 | 5298 |           CONF_Ind[0]=5; | 
 | 5299 |           CONF_Ind[3]=2; | 
 | 5300 |           PUT_WORD(&CONF_Ind[1],S_CONF_DROP); | 
 | 5301 |           plci->ptyState = CONNECTED; | 
 | 5302 |           break; | 
 | 5303 |       case CONF_ISOLATE: | 
 | 5304 |           CONF_Ind[0]=5; | 
 | 5305 |           CONF_Ind[3]=2; | 
 | 5306 |           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE); | 
 | 5307 |           plci->ptyState = CONNECTED; | 
 | 5308 |           break; | 
 | 5309 |       case CONF_REATTACH: | 
 | 5310 |           CONF_Ind[0]=5; | 
 | 5311 |           CONF_Ind[3]=2; | 
 | 5312 |           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH); | 
 | 5313 |           plci->ptyState = CONNECTED; | 
 | 5314 |           break; | 
 | 5315 |       case CONF_ADD: | 
 | 5316 |           PUT_WORD(&CONF_Ind[1],S_CONF_ADD); | 
 | 5317 |           plci->relatedPTYPLCI = NULL; | 
 | 5318 |           tplci=plci->relatedPTYPLCI; | 
 | 5319 |           if(tplci) tplci->ptyState = CONNECTED; | 
 | 5320 |           plci->ptyState = CONNECTED; | 
 | 5321 |           break; | 
 | 5322 |       } | 
 | 5323 |            | 
 | 5324 |       if(pty_cai[2]!=0xff) | 
 | 5325 |       { | 
 | 5326 |         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]); | 
 | 5327 |       } | 
 | 5328 |       else | 
 | 5329 |       { | 
 | 5330 |         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond | 
 | 5331 |                                             within the required time */ | 
 | 5332 |       } | 
 | 5333 |  | 
 | 5334 |       PUT_DWORD(&CONF_Ind[6],0x0); | 
 | 5335 |       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind); | 
 | 5336 |       break; | 
 | 5337 |     } | 
 | 5338 |     break; | 
 | 5339 |  | 
 | 5340 |   /* Supplementary Service indicates success */ | 
 | 5341 |   case S_SERVICE: | 
 | 5342 |     dbug(1,dprintf("Service_Ind")); | 
 | 5343 |     PUT_WORD (&CF_Ind[4], 0); | 
 | 5344 |     switch (pty_cai[5]) | 
 | 5345 |     { | 
 | 5346 |     case THREE_PTY_END: | 
 | 5347 |     case THREE_PTY_BEGIN: | 
 | 5348 |     case ECT_EXECUTE: | 
 | 5349 |       if(!plci->relatedPTYPLCI) break; | 
 | 5350 |       tplci = plci->relatedPTYPLCI; | 
 | 5351 |       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id; | 
 | 5352 |       if(tplci->tel) rId|=EXT_CONTROLLER; | 
 | 5353 |       if(pty_cai[5]==ECT_EXECUTE) | 
 | 5354 |       { | 
 | 5355 |         PUT_WORD(&SS_Ind[1],S_ECT); | 
 | 5356 |  | 
 | 5357 |         if(plci->vswitchstate!=3) | 
 | 5358 |         { | 
 | 5359 |  | 
 | 5360 |         plci->ptyState = IDLE; | 
 | 5361 |         plci->relatedPTYPLCI = NULL; | 
 | 5362 |         plci->ptyState = 0; | 
 | 5363 |  | 
 | 5364 |         } | 
 | 5365 |  | 
 | 5366 |         dbug(1,dprintf("ECT OK")); | 
 | 5367 |         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind); | 
 | 5368 |  | 
 | 5369 |  | 
 | 5370 |  | 
 | 5371 |       } | 
 | 5372 |       else | 
 | 5373 |       { | 
 | 5374 |         switch (plci->ptyState) | 
 | 5375 |         { | 
 | 5376 |         case S_3PTY_BEGIN: | 
 | 5377 |           plci->ptyState = CONNECTED; | 
 | 5378 |           dbug(1,dprintf("3PTY ON")); | 
 | 5379 |           break; | 
 | 5380 |  | 
 | 5381 |         case S_3PTY_END: | 
 | 5382 |           plci->ptyState = IDLE; | 
 | 5383 |           plci->relatedPTYPLCI = NULL; | 
 | 5384 |           plci->ptyState = 0; | 
 | 5385 |           dbug(1,dprintf("3PTY OFF")); | 
 | 5386 |           break; | 
 | 5387 |         } | 
 | 5388 |         PUT_WORD(&SS_Ind[1],pty_cai[5]+3); | 
 | 5389 |         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind); | 
 | 5390 |       } | 
 | 5391 |       break; | 
 | 5392 |  | 
 | 5393 |     case CALL_DEFLECTION: | 
 | 5394 |       PUT_WORD(&SS_Ind[1],pty_cai[5]); | 
 | 5395 |       for(i=0; i<max_appl; i++) | 
 | 5396 |       { | 
 | 5397 |         if(application[i].CDEnable) | 
 | 5398 |         { | 
 | 5399 |           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 5400 |           application[i].CDEnable = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5401 |         } | 
 | 5402 |       } | 
 | 5403 |       break; | 
 | 5404 |  | 
 | 5405 |     case DEACTIVATION_DIVERSION: | 
 | 5406 |     case ACTIVATION_DIVERSION: | 
 | 5407 |       if(!plci->appl) break; | 
 | 5408 |       PUT_WORD(&CF_Ind[1],pty_cai[5]+2); | 
 | 5409 |       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle); | 
 | 5410 |       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind); | 
 | 5411 |       plci_remove(plci); | 
 | 5412 |       break; | 
 | 5413 |  | 
 | 5414 |     case DIVERSION_INTERROGATE_CFU: | 
 | 5415 |     case DIVERSION_INTERROGATE_CFB: | 
 | 5416 |     case DIVERSION_INTERROGATE_CFNR: | 
 | 5417 |     case DIVERSION_INTERROGATE_NUM: | 
 | 5418 |     case CCBS_REQUEST: | 
 | 5419 |     case CCBS_DEACTIVATE: | 
 | 5420 |     case CCBS_INTERROGATE: | 
 | 5421 |       if(!plci->appl) break; | 
 | 5422 |       switch (pty_cai[5]) | 
 | 5423 |       { | 
 | 5424 |         case DIVERSION_INTERROGATE_CFU: | 
 | 5425 |         case DIVERSION_INTERROGATE_CFB: | 
 | 5426 |         case DIVERSION_INTERROGATE_CFNR: | 
 | 5427 |           dbug(1,dprintf("Interr_Div")); | 
 | 5428 |           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION); | 
 | 5429 |           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | 
 | 5430 |           break; | 
 | 5431 |         case DIVERSION_INTERROGATE_NUM: | 
 | 5432 |           dbug(1,dprintf("Interr_Num")); | 
 | 5433 |           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS); | 
 | 5434 |           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | 
 | 5435 |           break; | 
 | 5436 |         case CCBS_REQUEST: | 
 | 5437 |           dbug(1,dprintf("CCBS Request")); | 
 | 5438 |           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST); | 
 | 5439 |           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | 
 | 5440 |           break; | 
 | 5441 |         case CCBS_DEACTIVATE: | 
 | 5442 |           dbug(1,dprintf("CCBS Deactivate")); | 
 | 5443 |           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE); | 
 | 5444 |           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | 
 | 5445 |           break; | 
 | 5446 |         case CCBS_INTERROGATE: | 
 | 5447 |           dbug(1,dprintf("CCBS Interrogate")); | 
 | 5448 |           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE); | 
 | 5449 |           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | 
 | 5450 |           break; | 
 | 5451 |       } | 
 | 5452 |       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */ | 
 | 5453 |       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle); | 
 | 5454 |       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai); | 
 | 5455 |       plci_remove(plci); | 
 | 5456 |       break; | 
 | 5457 |  | 
 | 5458 |     case ACTIVATION_MWI: | 
 | 5459 |     case DEACTIVATION_MWI: | 
 | 5460 |       if(pty_cai[5]==ACTIVATION_MWI) | 
 | 5461 |       { | 
 | 5462 |         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE); | 
 | 5463 |       } | 
 | 5464 |       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); | 
 | 5465 |       if(plci->cr_enquiry) | 
 | 5466 |       { | 
 | 5467 |         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind); | 
 | 5468 |         plci_remove(plci); | 
 | 5469 |       } | 
 | 5470 |       else | 
 | 5471 |       { | 
 | 5472 |         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | 
 | 5473 |       } | 
 | 5474 |       break; | 
 | 5475 |     case MWI_INDICATION: | 
 | 5476 |       if(pty_cai[0]>=0x12) | 
 | 5477 |       { | 
 | 5478 |         PUT_WORD(&pty_cai[3],S_MWI_INDICATE); | 
 | 5479 |         pty_cai[2]=pty_cai[0]-2; /* len Parameter */ | 
 | 5480 |         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */ | 
 | 5481 |         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI)) | 
 | 5482 |         { | 
 | 5483 |           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */ | 
 | 5484 |           { | 
 | 5485 |             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]); | 
 | 5486 |             plci_remove(plci); | 
 | 5487 |             return; | 
 | 5488 |           } | 
 | 5489 |           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]); | 
 | 5490 |           pty_cai[0]=0; | 
 | 5491 |         } | 
 | 5492 |         else | 
 | 5493 |         { | 
 | 5494 |           for(i=0; i<max_appl; i++) | 
 | 5495 |           {                      | 
 | 5496 |             if(a->Notification_Mask[i]&SMASK_MWI) | 
 | 5497 |             { | 
 | 5498 |               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]); | 
 | 5499 |               pty_cai[0]=0; | 
 | 5500 |             } | 
 | 5501 |           } | 
 | 5502 |         } | 
 | 5503 |  | 
 | 5504 |         if(!pty_cai[0]) | 
 | 5505 |         { /* acknowledge */ | 
 | 5506 |           facility[2]= 0; /* returncode */ | 
 | 5507 |         } | 
 | 5508 |         else facility[2]= 0xff; | 
 | 5509 |       } | 
 | 5510 |       else | 
 | 5511 |       { | 
 | 5512 |         /* reject */ | 
 | 5513 |         facility[2]= 0xff; /* returncode */ | 
 | 5514 |       } | 
 | 5515 |       facility[0]= 2; | 
 | 5516 |       facility[1]= MWI_RESPONSE; /* Function */ | 
 | 5517 |       add_p(plci,CAI,facility); | 
 | 5518 |       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */ | 
 | 5519 |       sig_req(plci,S_SERVICE,0); | 
 | 5520 |       send_req(plci); | 
 | 5521 |       plci->command = 0; | 
 | 5522 |       next_internal_command (Id, plci); | 
 | 5523 |       break; | 
 | 5524 |     case CONF_ADD: /* OK */ | 
 | 5525 |     case CONF_BEGIN: | 
 | 5526 |     case CONF_DROP: | 
 | 5527 |     case CONF_ISOLATE: | 
 | 5528 |     case CONF_REATTACH: | 
 | 5529 |     case CONF_PARTYDISC: | 
 | 5530 |       CONF_Ind[0]=9; | 
 | 5531 |       CONF_Ind[3]=6; | 
 | 5532 |       switch(pty_cai[5]) | 
 | 5533 |       { | 
 | 5534 |       case CONF_BEGIN: | 
 | 5535 |           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN); | 
 | 5536 |           if(pty_cai[0]==6) | 
 | 5537 |           { | 
 | 5538 |               d=pty_cai[6]; | 
 | 5539 |               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */ | 
 | 5540 |           } | 
 | 5541 |           else | 
 | 5542 |           { | 
 | 5543 |               PUT_DWORD(&CONF_Ind[6],0x0); | 
 | 5544 |           } | 
 | 5545 |           break; | 
 | 5546 |       case CONF_ISOLATE: | 
 | 5547 |           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE); | 
 | 5548 |           CONF_Ind[0]=5; | 
 | 5549 |           CONF_Ind[3]=2; | 
 | 5550 |           break; | 
 | 5551 |       case CONF_REATTACH: | 
 | 5552 |           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH); | 
 | 5553 |           CONF_Ind[0]=5; | 
 | 5554 |           CONF_Ind[3]=2; | 
 | 5555 |           break; | 
 | 5556 |       case CONF_DROP: | 
 | 5557 |           PUT_WORD(&CONF_Ind[1],S_CONF_DROP); | 
 | 5558 |           CONF_Ind[0]=5; | 
 | 5559 |           CONF_Ind[3]=2; | 
 | 5560 |           break; | 
 | 5561 |       case CONF_ADD: | 
 | 5562 |           PUT_WORD(&CONF_Ind[1],S_CONF_ADD); | 
 | 5563 |           d=pty_cai[6]; | 
 | 5564 |           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */ | 
 | 5565 |           tplci=plci->relatedPTYPLCI; | 
 | 5566 |           if(tplci) tplci->ptyState = CONNECTED; | 
 | 5567 |           break; | 
 | 5568 |       case CONF_PARTYDISC: | 
 | 5569 |           CONF_Ind[0]=7; | 
 | 5570 |           CONF_Ind[3]=4;           | 
 | 5571 |           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC); | 
 | 5572 |           d=pty_cai[6]; | 
 | 5573 |           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */ | 
 | 5574 |           break; | 
 | 5575 |       } | 
 | 5576 |       plci->ptyState = CONNECTED; | 
 | 5577 |       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind); | 
 | 5578 |       break; | 
 | 5579 |     case CCBS_INFO_RETAIN: | 
 | 5580 |     case CCBS_ERASECALLLINKAGEID: | 
 | 5581 |     case CCBS_STOP_ALERTING: | 
 | 5582 |       CONF_Ind[0]=5; | 
 | 5583 |       CONF_Ind[3]=2; | 
 | 5584 |       switch(pty_cai[5]) | 
 | 5585 |       { | 
 | 5586 |       case CCBS_INFO_RETAIN: | 
 | 5587 |         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN); | 
 | 5588 |         break; | 
 | 5589 |       case CCBS_STOP_ALERTING: | 
 | 5590 |         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING); | 
 | 5591 |     break; | 
 | 5592 |       case CCBS_ERASECALLLINKAGEID: | 
 | 5593 |         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID); | 
 | 5594 |         CONF_Ind[0]=7; | 
 | 5595 |         CONF_Ind[3]=4; | 
 | 5596 |         CONF_Ind[6]=0; | 
 | 5597 |         CONF_Ind[7]=0; | 
 | 5598 |         break; | 
 | 5599 |       }       | 
 | 5600 |       w=pty_cai[6]; | 
 | 5601 |       PUT_WORD(&CONF_Ind[4],w); /* PartyID */ | 
 | 5602 |  | 
 | 5603 |       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS)) | 
 | 5604 |       { | 
 | 5605 |         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind); | 
 | 5606 |       } | 
 | 5607 |       else | 
 | 5608 |       { | 
 | 5609 |         for(i=0; i<max_appl; i++) | 
 | 5610 |             if(a->Notification_Mask[i]&SMASK_CCBS) | 
 | 5611 |                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind); | 
 | 5612 |       } | 
 | 5613 |       break; | 
 | 5614 |     } | 
 | 5615 |     break; | 
 | 5616 |   case CALL_HOLD_REJ: | 
 | 5617 |     cau = parms[7]; | 
 | 5618 |     if(cau) | 
 | 5619 |     { | 
 | 5620 |       i = _L3_CAUSE | cau[2]; | 
 | 5621 |       if(cau[2]==0) i = 0x3603; | 
 | 5622 |     } | 
 | 5623 |     else | 
 | 5624 |     { | 
 | 5625 |       i = 0x3603; | 
 | 5626 |     } | 
 | 5627 |     PUT_WORD(&SS_Ind[1],S_HOLD); | 
 | 5628 |     PUT_WORD(&SS_Ind[4],i); | 
 | 5629 |     if(plci->SuppState == HOLD_REQUEST) | 
 | 5630 |     { | 
 | 5631 |       plci->SuppState = IDLE; | 
 | 5632 |       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | 
 | 5633 |     } | 
 | 5634 |     break; | 
 | 5635 |  | 
 | 5636 |   case CALL_HOLD_ACK: | 
 | 5637 |     if(plci->SuppState == HOLD_REQUEST) | 
 | 5638 |     { | 
 | 5639 |       plci->SuppState = CALL_HELD; | 
 | 5640 |       CodecIdCheck(a, plci); | 
 | 5641 |       start_internal_command (Id, plci, hold_save_command); | 
 | 5642 |     } | 
 | 5643 |     break; | 
 | 5644 |  | 
 | 5645 |   case CALL_RETRIEVE_REJ: | 
 | 5646 |     cau = parms[7]; | 
 | 5647 |     if(cau) | 
 | 5648 |     { | 
 | 5649 |       i = _L3_CAUSE | cau[2]; | 
 | 5650 |       if(cau[2]==0) i = 0x3603; | 
 | 5651 |     } | 
 | 5652 |     else | 
 | 5653 |     { | 
 | 5654 |       i = 0x3603; | 
 | 5655 |     } | 
 | 5656 |     PUT_WORD(&SS_Ind[1],S_RETRIEVE); | 
 | 5657 |     PUT_WORD(&SS_Ind[4],i); | 
 | 5658 |     if(plci->SuppState == RETRIEVE_REQUEST) | 
 | 5659 |     { | 
 | 5660 |       plci->SuppState = CALL_HELD; | 
 | 5661 |       CodecIdCheck(a, plci); | 
 | 5662 |       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | 
 | 5663 |     } | 
 | 5664 |     break; | 
 | 5665 |  | 
 | 5666 |   case CALL_RETRIEVE_ACK: | 
 | 5667 |     PUT_WORD(&SS_Ind[1],S_RETRIEVE); | 
 | 5668 |     if(plci->SuppState == RETRIEVE_REQUEST) | 
 | 5669 |     { | 
 | 5670 |       plci->SuppState = IDLE; | 
 | 5671 |       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; | 
 | 5672 |       plci->b_channel = esc_chi[esc_chi[0]]&0x1f; | 
 | 5673 |       if(plci->tel) | 
 | 5674 |       { | 
 | 5675 |         mixer_set_bchannel_id_esc (plci, plci->b_channel); | 
 | 5676 |         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel)); | 
 | 5677 |         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a); | 
 | 5678 |         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT) | 
 | 5679 |         { | 
 | 5680 |           dbug(1,dprintf("Get B-ch")); | 
 | 5681 |           start_internal_command (Id, plci, retrieve_restore_command); | 
 | 5682 |         } | 
 | 5683 |         else | 
 | 5684 |           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | 
 | 5685 |       } | 
 | 5686 |       else | 
 | 5687 |         start_internal_command (Id, plci, retrieve_restore_command); | 
 | 5688 |     } | 
 | 5689 |     break; | 
 | 5690 |  | 
 | 5691 |   case INDICATE_IND: | 
 | 5692 |     if(plci->State != LISTENING) { | 
 | 5693 |       sig_req(plci,HANGUP,0); | 
 | 5694 |       send_req(plci); | 
 | 5695 |       break; | 
 | 5696 |     } | 
 | 5697 |     cip = find_cip(a,parms[4],parms[6]); | 
 | 5698 |     cip_mask = 1L<<cip; | 
 | 5699 |     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask)); | 
 | 5700 |     clear_c_ind_mask (plci); | 
 | 5701 |     if (!remove_started && !a->adapter_disabled) | 
 | 5702 |     { | 
 | 5703 |       set_c_ind_mask_bit (plci, MAX_APPL); | 
 | 5704 |       group_optimization(a, plci); | 
 | 5705 |       for(i=0; i<max_appl; i++) { | 
 | 5706 |         if(application[i].Id | 
 | 5707 |         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask) | 
 | 5708 |         && CPN_filter_ok(parms[0],a,i) | 
 | 5709 |         && test_group_ind_mask_bit (plci, i) ) { | 
 | 5710 |           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] )); | 
 | 5711 |           set_c_ind_mask_bit (plci, i); | 
 | 5712 |           dump_c_ind_mask (plci); | 
 | 5713 |           plci->State = INC_CON_PENDING; | 
 | 5714 |           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) | | 
 | 5715 |             CALL_DIR_IN | CALL_DIR_ANSWER; | 
 | 5716 |           if(esc_chi[0]) { | 
 | 5717 |             plci->b_channel = esc_chi[esc_chi[0]]&0x1f; | 
 | 5718 |             mixer_set_bchannel_id_esc (plci, plci->b_channel); | 
 | 5719 |           } | 
 | 5720 |           /* if a listen on the ext controller is done, check if hook states */ | 
 | 5721 |           /* are supported or if just a on board codec must be activated     */ | 
 | 5722 |           if(a->codec_listen[i] && !a->AdvSignalPLCI) { | 
 | 5723 |             if(a->profile.Global_Options & HANDSET) | 
 | 5724 |               plci->tel = ADV_VOICE; | 
 | 5725 |             else if(a->profile.Global_Options & ON_BOARD_CODEC) | 
 | 5726 |               plci->tel = CODEC; | 
 | 5727 |             if(plci->tel) Id|=EXT_CONTROLLER; | 
 | 5728 |             a->codec_listen[i] = plci; | 
 | 5729 |           } | 
 | 5730 |  | 
 | 5731 |           sendf(&application[i],_CONNECT_I,Id,0, | 
 | 5732 |                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */ | 
 | 5733 |                              parms[0],    /* CalledPartyNumber   */ | 
 | 5734 |                              multi_CiPN_parms[0],    /* CallingPartyNumber  */ | 
 | 5735 |                              parms[2],    /* CalledPartySubad    */ | 
 | 5736 |                              parms[3],    /* CallingPartySubad   */ | 
 | 5737 |                              parms[4],    /* BearerCapability    */ | 
 | 5738 |                              parms[5],    /* LowLC               */ | 
 | 5739 |                              parms[6],    /* HighLC              */ | 
 | 5740 |                              ai_len,      /* nested struct add_i */ | 
 | 5741 |                              add_i[0],    /* B channel info    */ | 
 | 5742 |                              add_i[1],    /* keypad facility   */ | 
 | 5743 |                              add_i[2],    /* user user data    */ | 
 | 5744 |                              add_i[3],    /* nested facility   */ | 
 | 5745 |                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */ | 
 | 5746 |                              ); | 
 | 5747 |           SendSSExtInd(&application[i], | 
 | 5748 |                         plci, | 
 | 5749 |                         Id, | 
 | 5750 |                         multi_ssext_parms); | 
 | 5751 |           SendSetupInfo(&application[i], | 
 | 5752 |                         plci, | 
 | 5753 |                         Id, | 
 | 5754 |                         parms, | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 5755 |                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5756 |         } | 
 | 5757 |       } | 
 | 5758 |       clear_c_ind_mask_bit (plci, MAX_APPL); | 
 | 5759 |       dump_c_ind_mask (plci); | 
 | 5760 |     } | 
 | 5761 |     if(c_ind_mask_empty (plci)) { | 
 | 5762 |       sig_req(plci,HANGUP,0); | 
 | 5763 |       send_req(plci); | 
 | 5764 |       plci->State = IDLE; | 
 | 5765 |     } | 
 | 5766 |     plci->notifiedcall = 0; | 
 | 5767 |     a->listen_active--; | 
 | 5768 |     listen_check(a); | 
 | 5769 |     break; | 
 | 5770 |  | 
 | 5771 |   case CALL_PEND_NOTIFY: | 
 | 5772 |     plci->notifiedcall = 1; | 
 | 5773 |     listen_check(a); | 
 | 5774 |     break; | 
 | 5775 |  | 
 | 5776 |   case CALL_IND: | 
 | 5777 |   case CALL_CON: | 
 | 5778 |     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG) | 
 | 5779 |     { | 
 | 5780 |       if(plci->internal_command==PERM_COD_CONN_PEND) | 
 | 5781 |       { | 
 | 5782 |         if(plci->State==ADVANCED_VOICE_NOSIG) | 
 | 5783 |         { | 
 | 5784 |           dbug(1,dprintf("***Codec OK")); | 
 | 5785 |           if(a->AdvSignalPLCI) | 
 | 5786 |           { | 
 | 5787 |             tplci = a->AdvSignalPLCI; | 
 | 5788 |             if(tplci->spoofed_msg) | 
 | 5789 |             { | 
 | 5790 |               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg)); | 
 | 5791 |               tplci->command = 0; | 
 | 5792 |               tplci->internal_command = 0; | 
 | 5793 |               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80; | 
 | 5794 |               switch (tplci->spoofed_msg) | 
 | 5795 |               { | 
 | 5796 |               case CALL_RES: | 
 | 5797 |                 tplci->command = _CONNECT_I|RESPONSE; | 
 | 5798 |                 api_load_msg (&tplci->saved_msg, saved_parms); | 
 | 5799 |                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities); | 
 | 5800 |                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200) | 
 | 5801 |                 { | 
 | 5802 |                   /* early B3 connect (CIP mask bit 9) no release after a disc */ | 
 | 5803 |                   add_p(tplci,LLI,"\x01\x01"); | 
 | 5804 |                 } | 
 | 5805 |                 add_s(tplci, CONN_NR, &saved_parms[2]); | 
 | 5806 |                 add_s(tplci, LLC, &saved_parms[4]); | 
 | 5807 |                 add_ai(tplci, &saved_parms[5]); | 
 | 5808 |                 tplci->State = INC_CON_ACCEPT; | 
 | 5809 |                 sig_req(tplci, CALL_RES,0); | 
 | 5810 |                 send_req(tplci); | 
 | 5811 |                 break; | 
 | 5812 |  | 
 | 5813 |               case AWAITING_SELECT_B: | 
 | 5814 |                 dbug(1,dprintf("Select_B continue")); | 
 | 5815 |                 start_internal_command (x_Id, tplci, select_b_command); | 
 | 5816 |                 break; | 
 | 5817 |  | 
 | 5818 |               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */ | 
 | 5819 |                 if(!tplci->Sig.Id) | 
 | 5820 |                 { | 
 | 5821 |                   dbug(1,dprintf("No SigID!")); | 
 | 5822 |                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI); | 
 | 5823 |                   plci_remove(tplci); | 
 | 5824 |                   break; | 
 | 5825 |                 } | 
 | 5826 |                 tplci->command = _MANUFACTURER_R; | 
 | 5827 |                 api_load_msg (&tplci->saved_msg, saved_parms); | 
 | 5828 |                 dir = saved_parms[2].info[0]; | 
 | 5829 |                 if(dir==1) { | 
 | 5830 |                   sig_req(tplci,CALL_REQ,0); | 
 | 5831 |                 } | 
 | 5832 |                 else if(!dir){ | 
 | 5833 |                   sig_req(tplci,LISTEN_REQ,0); | 
 | 5834 |                 } | 
 | 5835 |                 send_req(tplci); | 
 | 5836 |                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0); | 
 | 5837 |                 break; | 
 | 5838 |  | 
 | 5839 |               case (CALL_REQ|AWAITING_MANUF_CON): | 
 | 5840 |                 sig_req(tplci,CALL_REQ,0); | 
 | 5841 |                 send_req(tplci); | 
 | 5842 |                 break; | 
 | 5843 |  | 
 | 5844 |               case CALL_REQ: | 
 | 5845 |                 if(!tplci->Sig.Id) | 
 | 5846 |                 { | 
 | 5847 |                   dbug(1,dprintf("No SigID!")); | 
 | 5848 |                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI); | 
 | 5849 |                   plci_remove(tplci); | 
 | 5850 |                   break; | 
 | 5851 |                 } | 
 | 5852 |                 tplci->command = _CONNECT_R; | 
 | 5853 |                 api_load_msg (&tplci->saved_msg, saved_parms); | 
 | 5854 |                 add_s(tplci,CPN,&saved_parms[1]); | 
 | 5855 |                 add_s(tplci,DSA,&saved_parms[3]); | 
 | 5856 |                 add_ai(tplci,&saved_parms[9]); | 
 | 5857 |                 sig_req(tplci,CALL_REQ,0); | 
 | 5858 |                 send_req(tplci); | 
 | 5859 |                 break; | 
 | 5860 |  | 
 | 5861 |               case CALL_RETRIEVE: | 
 | 5862 |                 tplci->command = C_RETRIEVE_REQ; | 
 | 5863 |                 sig_req(tplci,CALL_RETRIEVE,0); | 
 | 5864 |                 send_req(tplci); | 
 | 5865 |                 break; | 
 | 5866 |               } | 
 | 5867 |               tplci->spoofed_msg = 0; | 
 | 5868 |               if (tplci->internal_command == 0) | 
 | 5869 |                 next_internal_command (x_Id, tplci); | 
 | 5870 |             } | 
 | 5871 |           } | 
 | 5872 |           next_internal_command (Id, plci); | 
 | 5873 |           break; | 
 | 5874 |         } | 
 | 5875 |         dbug(1,dprintf("***Codec Hook Init Req")); | 
 | 5876 |         plci->internal_command = PERM_COD_HOOK; | 
 | 5877 |         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/ | 
 | 5878 |         sig_req(plci,TEL_CTRL,0); | 
 | 5879 |         send_req(plci); | 
 | 5880 |       } | 
 | 5881 |     } | 
 | 5882 |     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */ | 
 | 5883 |     && plci->State!=INC_ACT_PENDING) | 
 | 5884 |     { | 
 | 5885 |       mixer_set_bchannel_id_esc (plci, plci->b_channel); | 
 | 5886 |       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */ | 
 | 5887 |       { | 
 | 5888 |         chi[2] = plci->b_channel; | 
 | 5889 |         SetVoiceChannel(a->AdvCodecPLCI, chi, a); | 
 | 5890 |       } | 
 | 5891 |       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"",""); | 
 | 5892 |       plci->State = INC_ACT_PENDING; | 
 | 5893 |     } | 
 | 5894 |     break; | 
 | 5895 |  | 
 | 5896 |   case TEL_CTRL: | 
 | 5897 |     Number = 0; | 
 | 5898 |     ie = multi_fac_parms[0]; /* inspect the facility hook indications */ | 
 | 5899 |     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){ | 
 | 5900 |       switch (ie[1]&0x91) { | 
 | 5901 |         case 0x80:   /* hook off */ | 
 | 5902 |         case 0x81: | 
 | 5903 |           if(plci->internal_command==PERM_COD_HOOK) | 
 | 5904 |           { | 
 | 5905 |             dbug(1,dprintf("init:hook_off")); | 
 | 5906 |             plci->hook_state = ie[1]; | 
 | 5907 |             next_internal_command (Id, plci); | 
 | 5908 |             break; | 
 | 5909 |           } | 
 | 5910 |           else /* ignore doubled hook indications */ | 
 | 5911 |           { | 
 | 5912 |             if( ((plci->hook_state)&0xf0)==0x80) | 
 | 5913 |             { | 
 | 5914 |               dbug(1,dprintf("ignore hook")); | 
 | 5915 |               break; | 
 | 5916 |             } | 
 | 5917 |             plci->hook_state = ie[1]&0x91; | 
 | 5918 |           } | 
 | 5919 |           /* check for incoming call pending */ | 
 | 5920 |           /* and signal '+'.Appl must decide */ | 
 | 5921 |           /* with connect_res if call must   */ | 
 | 5922 |           /* accepted or not                 */ | 
 | 5923 |           for(i=0, tplci=NULL;i<max_appl;i++){ | 
 | 5924 |             if(a->codec_listen[i] | 
 | 5925 |             && (a->codec_listen[i]->State==INC_CON_PENDING | 
 | 5926 |               ||a->codec_listen[i]->State==INC_CON_ALERT) ){ | 
 | 5927 |               tplci = a->codec_listen[i]; | 
 | 5928 |               tplci->appl = &application[i]; | 
 | 5929 |             } | 
 | 5930 |           } | 
 | 5931 |           /* no incoming call, do outgoing call */ | 
 | 5932 |           /* and signal '+' if outg. setup   */ | 
 | 5933 |           if(!a->AdvSignalPLCI && !tplci){ | 
 | 5934 |             if((i=get_plci(a))) { | 
 | 5935 |               a->AdvSignalPLCI = &a->plci[i-1]; | 
 | 5936 |               tplci = a->AdvSignalPLCI; | 
 | 5937 |               tplci->tel  = ADV_VOICE; | 
 | 5938 |               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength); | 
 | 5939 |               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){ | 
 | 5940 |                 /* early B3 connect (CIP mask bit 9) no release after a disc */ | 
 | 5941 |                 add_p(tplci,LLI,"\x01\x01"); | 
 | 5942 |               } | 
 | 5943 |               add_p(tplci, CAI, voice_cai); | 
 | 5944 |               add_p(tplci, OAD, a->TelOAD); | 
 | 5945 |               add_p(tplci, OSA, a->TelOSA); | 
 | 5946 |               add_p(tplci,SHIFT|6,NULL); | 
 | 5947 |               add_p(tplci,SIN,"\x02\x01\x00"); | 
 | 5948 |               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 5949 |               sig_req(tplci,ASSIGN,DSIG_ID); | 
 | 5950 |               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ; | 
 | 5951 |               a->AdvSignalPLCI->command = 0; | 
 | 5952 |               tplci->appl = a->AdvSignalAppl; | 
 | 5953 |               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | 
 | 5954 |               send_req(tplci); | 
 | 5955 |             } | 
 | 5956 |  | 
 | 5957 |           } | 
 | 5958 |  | 
 | 5959 |           if(!tplci) break; | 
 | 5960 |           Id = ((word)tplci->Id<<8)|a->Id; | 
 | 5961 |           Id|=EXT_CONTROLLER; | 
 | 5962 |           sendf(tplci->appl, | 
 | 5963 |                 _FACILITY_I, | 
 | 5964 |                 Id, | 
 | 5965 |                 0, | 
 | 5966 |                 "ws", (word)0, "\x01+"); | 
 | 5967 |           break; | 
 | 5968 |  | 
 | 5969 |         case 0x90:   /* hook on  */ | 
 | 5970 |         case 0x91: | 
 | 5971 |           if(plci->internal_command==PERM_COD_HOOK) | 
 | 5972 |           { | 
 | 5973 |             dbug(1,dprintf("init:hook_on")); | 
 | 5974 |             plci->hook_state = ie[1]&0x91; | 
 | 5975 |             next_internal_command (Id, plci); | 
 | 5976 |             break; | 
 | 5977 |           } | 
 | 5978 |           else /* ignore doubled hook indications */ | 
 | 5979 |           { | 
 | 5980 |             if( ((plci->hook_state)&0xf0)==0x90) break; | 
 | 5981 |             plci->hook_state = ie[1]&0x91; | 
 | 5982 |           } | 
 | 5983 |           /* hangup the adv. voice call and signal '-' to the appl */ | 
 | 5984 |           if(a->AdvSignalPLCI) { | 
 | 5985 |             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id; | 
 | 5986 |             if(plci->tel) Id|=EXT_CONTROLLER; | 
 | 5987 |             sendf(a->AdvSignalAppl, | 
 | 5988 |                   _FACILITY_I, | 
 | 5989 |                   Id, | 
 | 5990 |                   0, | 
 | 5991 |                   "ws", (word)0, "\x01-"); | 
 | 5992 |             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ; | 
 | 5993 |             a->AdvSignalPLCI->command = 0; | 
 | 5994 |             sig_req(a->AdvSignalPLCI,HANGUP,0); | 
 | 5995 |             send_req(a->AdvSignalPLCI); | 
 | 5996 |           } | 
 | 5997 |           break; | 
 | 5998 |       } | 
 | 5999 |     } | 
 | 6000 |     break; | 
 | 6001 |  | 
 | 6002 |   case RESUME: | 
 | 6003 |     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1)); | 
 | 6004 |     PUT_WORD(&resume_cau[4],GOOD); | 
 | 6005 |     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau); | 
 | 6006 |     break; | 
 | 6007 |  | 
 | 6008 |   case SUSPEND: | 
 | 6009 |     clear_c_ind_mask (plci); | 
 | 6010 |  | 
 | 6011 |     if (plci->NL.Id && !plci->nl_remove_id) { | 
 | 6012 |       mixer_remove (plci); | 
 | 6013 |       nl_req_ncci(plci,REMOVE,0); | 
 | 6014 |     } | 
 | 6015 |     if (!plci->sig_remove_id) { | 
 | 6016 |       plci->internal_command = 0; | 
 | 6017 |       sig_req(plci,REMOVE,0); | 
 | 6018 |     } | 
 | 6019 |     send_req(plci); | 
 | 6020 |     if(!plci->channels) { | 
 | 6021 |       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00"); | 
 | 6022 |       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0); | 
 | 6023 |     } | 
 | 6024 |     break; | 
 | 6025 |  | 
 | 6026 |   case SUSPEND_REJ: | 
 | 6027 |     break; | 
 | 6028 |  | 
 | 6029 |   case HANGUP: | 
 | 6030 |     plci->hangup_flow_ctrl_timer=0; | 
 | 6031 |     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break; | 
 | 6032 |     cau = parms[7]; | 
 | 6033 |     if(cau) { | 
 | 6034 |       i = _L3_CAUSE | cau[2]; | 
 | 6035 |       if(cau[2]==0) i = 0; | 
 | 6036 |       else if(cau[2]==8) i = _L1_ERROR; | 
 | 6037 |       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR; | 
 | 6038 |       else if(cau[2]==5) i = _CAPI_GUARD_ERROR; | 
 | 6039 |     } | 
 | 6040 |     else { | 
 | 6041 |       i = _L3_ERROR; | 
 | 6042 |     } | 
 | 6043 |  | 
 | 6044 |     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) | 
 | 6045 |     { | 
 | 6046 |       for(i=0; i<max_appl; i++) | 
 | 6047 |       { | 
 | 6048 |         if(test_c_ind_mask_bit (plci, i)) | 
 | 6049 |           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0); | 
 | 6050 |       } | 
 | 6051 |     } | 
 | 6052 |     else | 
 | 6053 |     { | 
 | 6054 |       clear_c_ind_mask (plci); | 
 | 6055 |     } | 
 | 6056 |     if(!plci->appl) | 
 | 6057 |     { | 
 | 6058 |       if (plci->State == LISTENING) | 
 | 6059 |       { | 
 | 6060 |         plci->notifiedcall=0; | 
 | 6061 |         a->listen_active--; | 
 | 6062 |       } | 
 | 6063 |       plci->State = INC_DIS_PENDING; | 
 | 6064 |       if(c_ind_mask_empty (plci)) | 
 | 6065 |       { | 
 | 6066 |         plci->State = IDLE; | 
 | 6067 |         if (plci->NL.Id && !plci->nl_remove_id) | 
 | 6068 |         { | 
 | 6069 |           mixer_remove (plci); | 
 | 6070 |           nl_req_ncci(plci,REMOVE,0); | 
 | 6071 |         } | 
 | 6072 |         if (!plci->sig_remove_id) | 
 | 6073 |         { | 
 | 6074 |           plci->internal_command = 0; | 
 | 6075 |           sig_req(plci,REMOVE,0); | 
 | 6076 |         } | 
 | 6077 |         send_req(plci); | 
 | 6078 |       } | 
 | 6079 |     } | 
 | 6080 |     else | 
 | 6081 |     { | 
 | 6082 |         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */ | 
 | 6083 |         /* result in a second HANGUP! Don't generate another        */ | 
 | 6084 |         /* DISCONNECT                                               */ | 
 | 6085 |       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING) | 
 | 6086 |       { | 
 | 6087 |         if(plci->State==RESUMING) | 
 | 6088 |         { | 
 | 6089 |           PUT_WORD(&resume_cau[4],i); | 
 | 6090 |           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau); | 
 | 6091 |         } | 
 | 6092 |         plci->State = INC_DIS_PENDING; | 
 | 6093 |         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i); | 
 | 6094 |       } | 
 | 6095 |     } | 
 | 6096 |     break; | 
 | 6097 |  | 
 | 6098 |   case SSEXT_IND: | 
 | 6099 |     SendSSExtInd(NULL,plci,Id,multi_ssext_parms); | 
 | 6100 |     break; | 
 | 6101 |  | 
 | 6102 |   case VSWITCH_REQ: | 
 | 6103 |     VSwitchReqInd(plci,Id,multi_vswitch_parms); | 
 | 6104 |     break; | 
 | 6105 |   case VSWITCH_IND: | 
 | 6106 |  if(plci->relatedPTYPLCI && | 
 | 6107 |   plci->vswitchstate==3 && | 
 | 6108 |   plci->relatedPTYPLCI->vswitchstate==3 && | 
 | 6109 |   parms[MAXPARMSIDS-1][0]) | 
 | 6110 |  { | 
 | 6111 |   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]); | 
 | 6112 |   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0); | 
 | 6113 |   send_req(plci->relatedPTYPLCI); | 
 | 6114 |  } | 
 | 6115 |     else VSwitchReqInd(plci,Id,multi_vswitch_parms); | 
 | 6116 |     break; | 
 | 6117 |  | 
 | 6118 |   } | 
 | 6119 | } | 
 | 6120 |  | 
 | 6121 |  | 
 | 6122 | static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag) | 
 | 6123 | { | 
 | 6124 |   word i; | 
 | 6125 |   byte   * ie; | 
 | 6126 |   word Info_Number; | 
 | 6127 |   byte   * Info_Element; | 
 | 6128 |   word Info_Mask = 0; | 
 | 6129 |  | 
 | 6130 |   dbug(1,dprintf("SetupInfo")); | 
 | 6131 |  | 
 | 6132 |   for(i=0; i<MAXPARMSIDS; i++) { | 
 | 6133 |     ie = parms[i]; | 
 | 6134 |     Info_Number = 0; | 
 | 6135 |     Info_Element = ie; | 
 | 6136 |     if(ie[0]) { | 
 | 6137 |       switch(i) { | 
 | 6138 |       case 0: | 
 | 6139 |         dbug(1,dprintf("CPN ")); | 
 | 6140 |         Info_Number = 0x0070; | 
 | 6141 |         Info_Mask   = 0x80; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6142 |         Info_Sent_Flag = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6143 |         break; | 
 | 6144 |       case 8:  /* display      */ | 
 | 6145 |         dbug(1,dprintf("display(%d)",i)); | 
 | 6146 |         Info_Number = 0x0028; | 
 | 6147 |         Info_Mask = 0x04; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6148 |         Info_Sent_Flag = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6149 |         break; | 
 | 6150 |       case 16: /* Channel Id */ | 
 | 6151 |         dbug(1,dprintf("CHI")); | 
 | 6152 |         Info_Number = 0x0018; | 
 | 6153 |         Info_Mask = 0x100; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6154 |         Info_Sent_Flag = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6155 |         mixer_set_bchannel_id (plci, Info_Element); | 
 | 6156 |         break; | 
 | 6157 |       case 19: /* Redirected Number */ | 
 | 6158 |         dbug(1,dprintf("RDN")); | 
 | 6159 |         Info_Number = 0x0074; | 
 | 6160 |         Info_Mask = 0x400; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6161 |         Info_Sent_Flag = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6162 |         break; | 
 | 6163 |       case 20: /* Redirected Number extended */ | 
 | 6164 |         dbug(1,dprintf("RDX")); | 
 | 6165 |         Info_Number = 0x0073; | 
 | 6166 |         Info_Mask = 0x400; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6167 |         Info_Sent_Flag = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6168 |         break; | 
 | 6169 |       case 22: /* Redirecing Number  */ | 
 | 6170 |         dbug(1,dprintf("RIN")); | 
 | 6171 |         Info_Number = 0x0076; | 
 | 6172 |         Info_Mask = 0x400; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6173 |         Info_Sent_Flag = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6174 |         break; | 
 | 6175 |       default: | 
 | 6176 |         Info_Number = 0; | 
 | 6177 |         break; | 
 | 6178 |       } | 
 | 6179 |     } | 
 | 6180 |  | 
 | 6181 |     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */ | 
 | 6182 |       Info_Number = 0x8000 |5; | 
 | 6183 |       Info_Mask = 0x10; | 
 | 6184 |       Info_Element = ""; | 
 | 6185 |     } | 
 | 6186 |  | 
 | 6187 |     if(Info_Sent_Flag && Info_Number){ | 
 | 6188 |       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) { | 
 | 6189 |         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element); | 
 | 6190 |       } | 
 | 6191 |     } | 
 | 6192 |   } | 
 | 6193 | } | 
 | 6194 |  | 
 | 6195 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 6196 | static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6197 | { | 
 | 6198 |   word i; | 
 | 6199 |   word j; | 
 | 6200 |   word k; | 
 | 6201 |   byte   * ie; | 
 | 6202 |   word Info_Number; | 
 | 6203 |   byte   * Info_Element; | 
 | 6204 |   word Info_Mask = 0; | 
 | 6205 |   static byte charges[5] = {4,0,0,0,0}; | 
 | 6206 |   static byte cause[] = {0x02,0x80,0x00}; | 
 | 6207 |   APPL   *appl; | 
 | 6208 |  | 
 | 6209 |   dbug(1,dprintf("InfoParse ")); | 
 | 6210 |  | 
 | 6211 |   if( | 
 | 6212 |         !plci->appl | 
 | 6213 |         && !plci->State | 
 | 6214 |         && plci->Sig.Ind!=NCR_FACILITY | 
 | 6215 |       ) | 
 | 6216 |   { | 
 | 6217 |     dbug(1,dprintf("NoParse ")); | 
 | 6218 |     return; | 
 | 6219 |   } | 
 | 6220 |   cause[2] = 0; | 
 | 6221 |   for(i=0; i<MAXPARMSIDS; i++) { | 
 | 6222 |     ie = parms[i]; | 
 | 6223 |     Info_Number = 0; | 
 | 6224 |     Info_Element = ie; | 
 | 6225 |     if(ie[0]) { | 
 | 6226 |       switch(i) { | 
 | 6227 |       case 0: | 
 | 6228 |         dbug(1,dprintf("CPN ")); | 
 | 6229 |         Info_Number = 0x0070; | 
 | 6230 |         Info_Mask   = 0x80; | 
 | 6231 |         break; | 
 | 6232 |       case 7: /* ESC_CAU */ | 
 | 6233 |         dbug(1,dprintf("cau(0x%x)",ie[2])); | 
 | 6234 |         Info_Number = 0x0008; | 
 | 6235 |         Info_Mask = 0x00; | 
 | 6236 |         cause[2] = ie[2]; | 
 | 6237 |         Info_Element = NULL; | 
 | 6238 |         break; | 
 | 6239 |       case 8:  /* display      */ | 
 | 6240 |         dbug(1,dprintf("display(%d)",i)); | 
 | 6241 |         Info_Number = 0x0028; | 
 | 6242 |         Info_Mask = 0x04; | 
 | 6243 |         break; | 
 | 6244 |       case 9:  /* Date display */ | 
 | 6245 |         dbug(1,dprintf("date(%d)",i)); | 
 | 6246 |         Info_Number = 0x0029; | 
 | 6247 |         Info_Mask = 0x02; | 
 | 6248 |         break; | 
 | 6249 |       case 10: /* charges */ | 
 | 6250 |         for(j=0;j<4;j++) charges[1+j] = 0; | 
 | 6251 |         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++); | 
 | 6252 |         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j]; | 
 | 6253 |         Info_Number = 0x4000; | 
 | 6254 |         Info_Mask = 0x40; | 
 | 6255 |         Info_Element = charges; | 
 | 6256 |         break; | 
 | 6257 |       case 11: /* user user info */ | 
 | 6258 |         dbug(1,dprintf("uui")); | 
 | 6259 |         Info_Number = 0x007E; | 
 | 6260 |         Info_Mask = 0x08; | 
 | 6261 |         break; | 
 | 6262 |       case 12: /* congestion receiver ready */ | 
 | 6263 |         dbug(1,dprintf("clRDY")); | 
 | 6264 |         Info_Number = 0x00B0; | 
 | 6265 |         Info_Mask = 0x08; | 
 | 6266 |         Info_Element = ""; | 
 | 6267 |         break; | 
 | 6268 |       case 13: /* congestion receiver not ready */ | 
 | 6269 |         dbug(1,dprintf("clNRDY")); | 
 | 6270 |         Info_Number = 0x00BF; | 
 | 6271 |         Info_Mask = 0x08; | 
 | 6272 |         Info_Element = ""; | 
 | 6273 |         break; | 
 | 6274 |       case 15: /* Keypad Facility */ | 
 | 6275 |         dbug(1,dprintf("KEY")); | 
 | 6276 |         Info_Number = 0x002C; | 
 | 6277 |         Info_Mask = 0x20; | 
 | 6278 |         break; | 
 | 6279 |       case 16: /* Channel Id */ | 
 | 6280 |         dbug(1,dprintf("CHI")); | 
 | 6281 |         Info_Number = 0x0018; | 
 | 6282 |         Info_Mask = 0x100; | 
 | 6283 |         mixer_set_bchannel_id (plci, Info_Element); | 
 | 6284 |         break; | 
 | 6285 |       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */ | 
 | 6286 |         dbug(1,dprintf("q9cau(0x%x)",ie[2])); | 
 | 6287 |         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */ | 
 | 6288 |         Info_Number = 0x0008; | 
 | 6289 |         Info_Mask = 0x01; | 
 | 6290 |         if(cause[2] != ie[2]) Info_Element = cause; | 
 | 6291 |         break; | 
 | 6292 |       case 19: /* Redirected Number */ | 
 | 6293 |         dbug(1,dprintf("RDN")); | 
 | 6294 |         Info_Number = 0x0074; | 
 | 6295 |         Info_Mask = 0x400; | 
 | 6296 |         break; | 
 | 6297 |       case 22: /* Redirecing Number  */ | 
 | 6298 |         dbug(1,dprintf("RIN")); | 
 | 6299 |         Info_Number = 0x0076; | 
 | 6300 |         Info_Mask = 0x400; | 
 | 6301 |         break; | 
 | 6302 |       case 23: /* Notification Indicator  */ | 
 | 6303 |         dbug(1,dprintf("NI")); | 
 | 6304 |         Info_Number = (word)NI; | 
 | 6305 |         Info_Mask = 0x210; | 
 | 6306 |         break; | 
 | 6307 |       case 26: /* Call State  */ | 
 | 6308 |         dbug(1,dprintf("CST")); | 
 | 6309 |         Info_Number = (word)CST; | 
 | 6310 |         Info_Mask = 0x01; /* do with cause i.e. for now */ | 
 | 6311 |         break; | 
 | 6312 |       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */ | 
 | 6313 |         dbug(1,dprintf("ESC/MT[0x%x]",ie[3])); | 
 | 6314 |         Info_Number = 0x8000 |ie[3]; | 
 | 6315 |         if(iesent) Info_Mask = 0xffff; | 
 | 6316 |         else  Info_Mask = 0x10; | 
 | 6317 |         Info_Element = ""; | 
 | 6318 |         break; | 
 | 6319 |       default: | 
 | 6320 |         Info_Number  = 0; | 
 | 6321 |         Info_Mask    = 0; | 
 | 6322 |         Info_Element = ""; | 
 | 6323 |         break; | 
 | 6324 |       } | 
 | 6325 |     } | 
 | 6326 |  | 
 | 6327 |     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */ | 
 | 6328 |     { | 
 | 6329 |       for(j=0; j<max_appl; j++) | 
 | 6330 |       { | 
 | 6331 |         appl = &application[j]; | 
 | 6332 |         if(Info_Number | 
 | 6333 |         && appl->Id | 
 | 6334 |         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask) | 
 | 6335 |         { | 
 | 6336 |           dbug(1,dprintf("NCR_Ind")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6337 |           iesent=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6338 |           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element); | 
 | 6339 |         } | 
 | 6340 |       } | 
 | 6341 |     } | 
 | 6342 |     else if(!plci->appl) | 
 | 6343 |     { /* overlap receiving broadcast */ | 
 | 6344 |       if(Info_Number==CPN | 
 | 6345 |       || Info_Number==KEY | 
 | 6346 |       || Info_Number==NI | 
 | 6347 |       || Info_Number==DSP | 
 | 6348 |       || Info_Number==UUI ) | 
 | 6349 |       { | 
 | 6350 |         for(j=0; j<max_appl; j++) | 
 | 6351 |         { | 
 | 6352 |           if(test_c_ind_mask_bit (plci, j)) | 
 | 6353 |           { | 
 | 6354 |             dbug(1,dprintf("Ovl_Ind")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6355 |             iesent=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6356 |             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element); | 
 | 6357 |           } | 
 | 6358 |         } | 
 | 6359 |       } | 
 | 6360 |     }               /* all other signalling states */ | 
 | 6361 |     else if(Info_Number | 
 | 6362 |     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask) | 
 | 6363 |     { | 
 | 6364 |       dbug(1,dprintf("Std_Ind")); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6365 |       iesent=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6366 |       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element); | 
 | 6367 |     } | 
 | 6368 |   } | 
 | 6369 | } | 
 | 6370 |  | 
 | 6371 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 6372 | static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, | 
 | 6373 | 			dword info_mask, byte setupParse) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6374 | { | 
 | 6375 |   word i; | 
 | 6376 |   word j; | 
 | 6377 |   byte   * ie; | 
 | 6378 |   word Info_Number; | 
 | 6379 |   byte   * Info_Element; | 
 | 6380 |   APPL   *appl; | 
 | 6381 |   word Info_Mask = 0; | 
 | 6382 |   byte iesent=0; | 
 | 6383 |  | 
 | 6384 |   if( | 
 | 6385 |       !plci->appl | 
 | 6386 |       && !plci->State | 
 | 6387 |       && plci->Sig.Ind!=NCR_FACILITY | 
 | 6388 |       && !setupParse | 
 | 6389 |       ) | 
 | 6390 |   { | 
 | 6391 |     dbug(1,dprintf("NoM-IEParse ")); | 
 | 6392 |     return 0; | 
 | 6393 |   } | 
 | 6394 |   dbug(1,dprintf("M-IEParse ")); | 
 | 6395 |  | 
 | 6396 |   for(i=0; i<MAX_MULTI_IE; i++) | 
 | 6397 |   { | 
 | 6398 |     ie = parms[i]; | 
 | 6399 |     Info_Number = 0; | 
 | 6400 |     Info_Element = ie; | 
 | 6401 |     if(ie[0]) | 
 | 6402 |     { | 
 | 6403 |       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type)); | 
 | 6404 |       Info_Number = (word)ie_type; | 
 | 6405 |       Info_Mask = (word)info_mask; | 
 | 6406 |     } | 
 | 6407 |  | 
 | 6408 |     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */ | 
 | 6409 |     { | 
 | 6410 |       for(j=0; j<max_appl; j++) | 
 | 6411 |       { | 
 | 6412 |         appl = &application[j]; | 
 | 6413 |         if(Info_Number | 
 | 6414 |         && appl->Id | 
 | 6415 |         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask) | 
 | 6416 |         { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6417 |           iesent = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6418 |           dbug(1,dprintf("Mlt_NCR_Ind")); | 
 | 6419 |           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element); | 
 | 6420 |         } | 
 | 6421 |       } | 
 | 6422 |     } | 
 | 6423 |     else if(!plci->appl && Info_Number) | 
 | 6424 |     {                                        /* overlap receiving broadcast */ | 
 | 6425 |       for(j=0; j<max_appl; j++) | 
 | 6426 |       { | 
 | 6427 |         if(test_c_ind_mask_bit (plci, j)) | 
 | 6428 |         { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6429 |           iesent = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6430 |           dbug(1,dprintf("Mlt_Ovl_Ind")); | 
 | 6431 |           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element); | 
 | 6432 |         } | 
 | 6433 |       } | 
 | 6434 |     }                                        /* all other signalling states */ | 
 | 6435 |     else if(Info_Number | 
 | 6436 |     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask) | 
 | 6437 |     { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6438 |       iesent = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6439 |       dbug(1,dprintf("Mlt_Std_Ind")); | 
 | 6440 |       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element); | 
 | 6441 |     } | 
 | 6442 |   } | 
 | 6443 |   return iesent; | 
 | 6444 | } | 
 | 6445 |  | 
 | 6446 | static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms) | 
 | 6447 | { | 
 | 6448 |   word i; | 
 | 6449 |    /* Format of multi_ssext_parms[i][]: | 
 | 6450 |    0 byte length | 
 | 6451 |    1 byte SSEXTIE | 
 | 6452 |    2 byte SSEXT_REQ/SSEXT_IND | 
 | 6453 |    3 byte length | 
 | 6454 |    4 word SSExtCommand | 
 | 6455 |    6... Params | 
 | 6456 |    */ | 
 | 6457 |   if( | 
 | 6458 |    plci | 
 | 6459 |    && plci->State | 
 | 6460 |    && plci->Sig.Ind!=NCR_FACILITY | 
 | 6461 |     ) | 
 | 6462 |  for(i=0;i<MAX_MULTI_IE;i++) | 
 | 6463 |     { | 
 | 6464 |       if(parms[i][0]<6) continue; | 
 | 6465 |    if(parms[i][2]==SSEXT_REQ) continue; | 
 | 6466 |  | 
 | 6467 |    if(appl) | 
 | 6468 |    { | 
 | 6469 |     parms[i][0]=0; /* kill it */ | 
 | 6470 |     sendf(appl,_MANUFACTURER_I, | 
 | 6471 |     Id, | 
 | 6472 |     0, | 
 | 6473 |     "dwS", | 
 | 6474 |     _DI_MANU_ID, | 
 | 6475 |     _DI_SSEXT_CTRL, | 
 | 6476 |     &parms[i][3]); | 
 | 6477 |    } | 
 | 6478 |    else if(plci->appl) | 
 | 6479 |    { | 
 | 6480 |     parms[i][0]=0; /* kill it */ | 
 | 6481 |     sendf(plci->appl,_MANUFACTURER_I, | 
 | 6482 |     Id, | 
 | 6483 |     0, | 
 | 6484 |     "dwS", | 
 | 6485 |     _DI_MANU_ID, | 
 | 6486 |     _DI_SSEXT_CTRL, | 
 | 6487 |     &parms[i][3]); | 
 | 6488 |    } | 
 | 6489 |     } | 
 | 6490 | }; | 
 | 6491 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 6492 | static void nl_ind(PLCI *plci) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6493 | { | 
 | 6494 |   byte ch; | 
 | 6495 |   word ncci; | 
 | 6496 |   dword Id; | 
 | 6497 |   DIVA_CAPI_ADAPTER   * a; | 
 | 6498 |   word NCCIcode; | 
 | 6499 |   APPL   * APPLptr; | 
 | 6500 |   word count; | 
 | 6501 |   word Num; | 
 | 6502 |   word i, ncpi_state; | 
 | 6503 |   byte len, ncci_state; | 
 | 6504 |   word msg; | 
 | 6505 |   word info = 0; | 
 | 6506 |   word fax_feature_bits; | 
 | 6507 |   byte fax_send_edata_ack; | 
 | 6508 |   static byte v120_header_buffer[2 + 3]; | 
 | 6509 |   static word fax_info[] = { | 
 | 6510 |     0,                     /* T30_SUCCESS                        */ | 
 | 6511 |     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */ | 
 | 6512 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */ | 
 | 6513 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */ | 
 | 6514 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */ | 
 | 6515 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */ | 
 | 6516 |     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */ | 
 | 6517 |     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */ | 
 | 6518 |     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */ | 
 | 6519 |     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */ | 
 | 6520 |     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */ | 
 | 6521 |     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */ | 
 | 6522 |     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */ | 
 | 6523 |     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */ | 
 | 6524 |     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */ | 
 | 6525 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */ | 
 | 6526 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */ | 
 | 6527 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */ | 
 | 6528 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */ | 
 | 6529 |     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */ | 
 | 6530 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */ | 
 | 6531 |     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */ | 
 | 6532 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */ | 
 | 6533 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */ | 
 | 6534 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */ | 
 | 6535 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */ | 
 | 6536 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */ | 
 | 6537 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */ | 
 | 6538 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */ | 
 | 6539 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */ | 
 | 6540 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */ | 
 | 6541 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */ | 
 | 6542 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */ | 
 | 6543 |     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */ | 
 | 6544 |     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */ | 
 | 6545 |     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */ | 
 | 6546 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */ | 
 | 6547 |     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */ | 
 | 6548 |     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */ | 
 | 6549 |     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */ | 
 | 6550 |     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */ | 
 | 6551 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */ | 
 | 6552 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */ | 
 | 6553 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */ | 
 | 6554 |     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */ | 
 | 6555 |     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */ | 
 | 6556 |     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */ | 
 | 6557 |   }; | 
 | 6558 |  | 
 | 6559 |     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1]; | 
 | 6560 |  | 
 | 6561 |  | 
 | 6562 |   static word rtp_info[] = { | 
 | 6563 |     GOOD,                  /* RTP_SUCCESS                       */ | 
 | 6564 |     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */ | 
 | 6565 |   }; | 
 | 6566 |  | 
 | 6567 |   static dword udata_forwarding_table[0x100 / sizeof(dword)] = | 
 | 6568 |   { | 
 | 6569 |     0x0020301e, 0x00000000, 0x00000000, 0x00000000, | 
 | 6570 |     0x00000000, 0x00000000, 0x00000000, 0x00000000 | 
 | 6571 |   }; | 
 | 6572 |  | 
 | 6573 |   ch = plci->NL.IndCh; | 
 | 6574 |   a = plci->adapter; | 
 | 6575 |   ncci = a->ch_ncci[ch]; | 
 | 6576 |   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id; | 
 | 6577 |   if(plci->tel) Id|=EXT_CONTROLLER; | 
 | 6578 |   APPLptr = plci->appl; | 
 | 6579 |   dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x", | 
 | 6580 |     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f)); | 
 | 6581 |  | 
 | 6582 |   /* in the case if no connect_active_Ind was sent to the appl we wait for */ | 
 | 6583 |  | 
 | 6584 |   if (plci->nl_remove_id) | 
 | 6585 |   { | 
 | 6586 |     plci->NL.RNR = 2; /* discard */ | 
 | 6587 |     dbug(1,dprintf("NL discard while remove pending")); | 
 | 6588 |     return; | 
 | 6589 |   } | 
 | 6590 |   if((plci->NL.Ind &0x0f)==N_CONNECT) | 
 | 6591 |   { | 
 | 6592 |     if(plci->State==INC_DIS_PENDING | 
 | 6593 |     || plci->State==OUTG_DIS_PENDING | 
 | 6594 |     || plci->State==IDLE) | 
 | 6595 |     { | 
 | 6596 |       plci->NL.RNR = 2; /* discard */ | 
 | 6597 |       dbug(1,dprintf("discard n_connect")); | 
 | 6598 |       return; | 
 | 6599 |     } | 
 | 6600 |     if(plci->State < INC_ACT_PENDING) | 
 | 6601 |     { | 
 | 6602 |       plci->NL.RNR = 1; /* flow control */ | 
 | 6603 |       channel_x_off (plci, ch, N_XON_CONNECT_IND); | 
 | 6604 |       return; | 
 | 6605 |     } | 
 | 6606 |   } | 
 | 6607 |  | 
 | 6608 |   if(!APPLptr)                         /* no application or invalid data */ | 
 | 6609 |   {                                    /* while reloading the DSP        */ | 
 | 6610 |     dbug(1,dprintf("discard1")); | 
 | 6611 |     plci->NL.RNR = 2; | 
 | 6612 |     return; | 
 | 6613 |   } | 
 | 6614 |  | 
 | 6615 |   if (((plci->NL.Ind &0x0f) == N_UDATA) | 
 | 6616 |      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18))) | 
 | 6617 |         || (plci->B2_prot == 7) | 
 | 6618 |         || (plci->B3_prot == 7)) ) | 
 | 6619 |   { | 
 | 6620 |     plci->ncpi_buffer[0] = 0; | 
 | 6621 |  | 
 | 6622 |     ncpi_state = plci->ncpi_state; | 
 | 6623 |     if (plci->NL.complete == 1) | 
 | 6624 |     { | 
 | 6625 |       byte  * data = &plci->NL.RBuffer->P[0]; | 
 | 6626 |  | 
 | 6627 |       if ((plci->NL.RBuffer->length >= 12) | 
 | 6628 |         &&( (*data == DSP_UDATA_INDICATION_DCD_ON) | 
 | 6629 |           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) ) | 
 | 6630 |       { | 
 | 6631 |         word conn_opt, ncpi_opt = 0x00; | 
 | 6632 | /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */ | 
 | 6633 |  | 
 | 6634 |         if (*data == DSP_UDATA_INDICATION_DCD_ON) | 
 | 6635 |           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED; | 
 | 6636 |         if (*data == DSP_UDATA_INDICATION_CTS_ON) | 
 | 6637 |           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED; | 
 | 6638 |  | 
 | 6639 |         data++;    /* indication code */ | 
 | 6640 |         data += 2; /* timestamp */ | 
 | 6641 |         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN)) | 
 | 6642 |           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED); | 
 | 6643 |         data++;    /* connected norm */ | 
 | 6644 |         conn_opt = GET_WORD(data); | 
 | 6645 |         data += 2; /* connected options */ | 
 | 6646 |  | 
 | 6647 |         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF)); | 
 | 6648 |  | 
 | 6649 |         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42) | 
 | 6650 |         { | 
 | 6651 |           ncpi_opt |= MDM_NCPI_ECM_V42; | 
 | 6652 |         } | 
 | 6653 |         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP) | 
 | 6654 |         { | 
 | 6655 |           ncpi_opt |= MDM_NCPI_ECM_MNP; | 
 | 6656 |         } | 
 | 6657 |         else | 
 | 6658 |         { | 
 | 6659 |           ncpi_opt |= MDM_NCPI_TRANSPARENT; | 
 | 6660 |         } | 
 | 6661 |         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION) | 
 | 6662 |         { | 
 | 6663 |           ncpi_opt |= MDM_NCPI_COMPRESSED; | 
 | 6664 |         } | 
 | 6665 |         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt); | 
 | 6666 |         plci->ncpi_buffer[0] = 4; | 
 | 6667 |  | 
 | 6668 |         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND; | 
 | 6669 |       } | 
 | 6670 |     } | 
 | 6671 |     if (plci->B3_prot == 7) | 
 | 6672 |     { | 
 | 6673 |       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING)) | 
 | 6674 |        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 6675 |        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | 
 | 6676 |       { | 
 | 6677 |         a->ncci_state[ncci] = INC_ACT_PENDING; | 
 | 6678 |         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | 
 | 6679 |         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | 
 | 6680 |       } | 
 | 6681 |     } | 
 | 6682 |  | 
 | 6683 |     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | 
 | 6684 |         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN))) | 
 | 6685 |      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED) | 
 | 6686 |      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED)) | 
 | 6687 |  | 
 | 6688 |     { | 
 | 6689 |       plci->NL.RNR = 2; | 
 | 6690 |       return; | 
 | 6691 |     } | 
 | 6692 |   } | 
 | 6693 |  | 
 | 6694 |   if(plci->NL.complete == 2) | 
 | 6695 |     { | 
 | 6696 |     if (((plci->NL.Ind &0x0f) == N_UDATA) | 
 | 6697 |      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f)))) | 
 | 6698 |     { | 
 | 6699 |       switch(plci->RData[0].P[0]) | 
 | 6700 |       { | 
 | 6701 |  | 
 | 6702 |       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE: | 
 | 6703 |         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG) | 
 | 6704 |           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X"); | 
 | 6705 |         break; | 
 | 6706 |       case DTMF_UDATA_INDICATION_ANSWER_TONE: | 
 | 6707 |         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG) | 
 | 6708 |           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y"); | 
 | 6709 |         break; | 
 | 6710 |       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED: | 
 | 6711 |         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | 
 | 6712 |         break; | 
 | 6713 |       case DTMF_UDATA_INDICATION_DIGITS_SENT: | 
 | 6714 |         dtmf_confirmation (Id, plci); | 
 | 6715 |         break; | 
 | 6716 |  | 
 | 6717 |  | 
 | 6718 |       case UDATA_INDICATION_MIXER_TAP_DATA: | 
 | 6719 |         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1)); | 
 | 6720 |  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1); | 
 | 6721 |  if (i != 0) | 
 | 6722 |  { | 
 | 6723 |    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED; | 
 | 6724 |           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1)); | 
 | 6725 |  } | 
 | 6726 |         break; | 
 | 6727 |  | 
 | 6728 |  | 
 | 6729 |       case UDATA_INDICATION_MIXER_COEFS_SET: | 
 | 6730 |         mixer_indication_coefs_set (Id, plci); | 
 | 6731 |         break; | 
 | 6732 |       case UDATA_INDICATION_XCONNECT_FROM: | 
 | 6733 |         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | 
 | 6734 |         break; | 
 | 6735 |       case UDATA_INDICATION_XCONNECT_TO: | 
 | 6736 |         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | 
 | 6737 |         break; | 
 | 6738 |  | 
 | 6739 |  | 
 | 6740 |       case LEC_UDATA_INDICATION_DISABLE_DETECT: | 
 | 6741 |         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | 
 | 6742 |         break; | 
 | 6743 |  | 
 | 6744 |  | 
 | 6745 |  | 
 | 6746 |       default: | 
 | 6747 |         break; | 
 | 6748 |       } | 
 | 6749 |     } | 
 | 6750 |     else | 
 | 6751 |   { | 
 | 6752 |       if ((plci->RData[0].PLength != 0) | 
 | 6753 |      && ((plci->B2_prot == B2_V120_ASYNC) | 
 | 6754 |       || (plci->B2_prot == B2_V120_ASYNC_V42BIS) | 
 | 6755 |       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))) | 
 | 6756 |     { | 
 | 6757 |  | 
 | 6758 |       sendf(plci->appl,_DATA_B3_I,Id,0, | 
 | 6759 |             "dwww", | 
 | 6760 |             plci->RData[1].P, | 
 | 6761 |               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength, | 
 | 6762 |             plci->RNum, | 
 | 6763 |             plci->RFlags); | 
 | 6764 |  | 
 | 6765 |     } | 
 | 6766 |     else | 
 | 6767 |     { | 
 | 6768 |  | 
 | 6769 |       sendf(plci->appl,_DATA_B3_I,Id,0, | 
 | 6770 |             "dwww", | 
 | 6771 |             plci->RData[0].P, | 
 | 6772 |             plci->RData[0].PLength, | 
 | 6773 |             plci->RNum, | 
 | 6774 |             plci->RFlags); | 
 | 6775 |  | 
 | 6776 |     } | 
 | 6777 |     } | 
 | 6778 |     return; | 
 | 6779 |   } | 
 | 6780 |  | 
 | 6781 |   fax_feature_bits = 0; | 
 | 6782 |   if((plci->NL.Ind &0x0f)==N_CONNECT || | 
 | 6783 |      (plci->NL.Ind &0x0f)==N_CONNECT_ACK || | 
 | 6784 |      (plci->NL.Ind &0x0f)==N_DISC || | 
 | 6785 |      (plci->NL.Ind &0x0f)==N_EDATA || | 
 | 6786 |      (plci->NL.Ind &0x0f)==N_DISC_ACK) | 
 | 6787 |   { | 
 | 6788 |     info = 0; | 
 | 6789 |     plci->ncpi_buffer[0] = 0; | 
 | 6790 |     switch (plci->B3_prot) { | 
 | 6791 |     case  0: /*XPARENT*/ | 
 | 6792 |     case  1: /*T.90 NL*/ | 
 | 6793 |       break;    /* no network control protocol info - jfr */ | 
 | 6794 |     case  2: /*ISO8202*/ | 
 | 6795 |     case  3: /*X25 DCE*/ | 
 | 6796 |       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i]; | 
 | 6797 |       plci->ncpi_buffer[0] = (byte)(i+3); | 
 | 6798 |       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0); | 
 | 6799 |       plci->ncpi_buffer[2] = 0; | 
 | 6800 |       plci->ncpi_buffer[3] = 0; | 
 | 6801 |       break; | 
 | 6802 |     case  4: /*T.30 - FAX*/ | 
 | 6803 |     case  5: /*T.30 - FAX*/ | 
 | 6804 |       if(plci->NL.RLength>=sizeof(T30_INFO)) | 
 | 6805 |       { | 
 | 6806 |         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code)); | 
 | 6807 |         len = 9; | 
 | 6808 |         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400); | 
 | 6809 |         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low); | 
 | 6810 |         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000; | 
 | 6811 |         if (plci->B3_prot == 5) | 
 | 6812 |         { | 
 | 6813 |           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM)) | 
 | 6814 |             i |= 0x8000; /* This is not an ECM connection */ | 
 | 6815 |           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING) | 
 | 6816 |             i |= 0x4000; /* This is a connection with MMR compression */ | 
 | 6817 |           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING) | 
 | 6818 |             i |= 0x2000; /* This is a connection with MR compression */ | 
 | 6819 |           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS) | 
 | 6820 |             i |= 0x0004; /* More documents */ | 
 | 6821 |           if (fax_feature_bits & T30_FEATURE_BIT_POLLING) | 
 | 6822 |             i |= 0x0002; /* Fax-polling indication */ | 
 | 6823 |         } | 
 | 6824 |         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i)); | 
 | 6825 |         PUT_WORD(&(plci->ncpi_buffer[3]),i); | 
 | 6826 |         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format); | 
 | 6827 |         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low; | 
 | 6828 |         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high; | 
 | 6829 |         plci->ncpi_buffer[len] = 0; | 
 | 6830 |         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len) | 
 | 6831 |         { | 
 | 6832 |           plci->ncpi_buffer[len] = 20; | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 6833 |           for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6834 |             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i]; | 
 | 6835 |         } | 
 | 6836 |         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)) | 
 | 6837 |         { | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 6838 | 	  if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6839 |             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code]; | 
 | 6840 |           else | 
 | 6841 |             info = _FAX_PROTOCOL_ERROR; | 
 | 6842 |         } | 
 | 6843 |  | 
 | 6844 |         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) | 
 | 6845 |           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | 
 | 6846 |         { | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 6847 |           i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6848 |           while (i < plci->NL.RBuffer->length) | 
 | 6849 |             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++]; | 
 | 6850 |         } | 
 | 6851 |  | 
 | 6852 |         plci->ncpi_buffer[0] = len; | 
 | 6853 |         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low); | 
 | 6854 |         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits); | 
 | 6855 |  | 
 | 6856 |         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND; | 
 | 6857 |  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK) | 
 | 6858 |          || (((plci->NL.Ind &0x0f) == N_CONNECT) | 
 | 6859 |           && (fax_feature_bits & T30_FEATURE_BIT_POLLING)) | 
 | 6860 |          || (((plci->NL.Ind &0x0f) == N_EDATA) | 
 | 6861 |           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK) | 
 | 6862 |            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS) | 
 | 6863 |            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC)))) | 
 | 6864 |  { | 
 | 6865 |           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT; | 
 | 6866 |  } | 
 | 6867 |  if (((plci->NL.Ind &0x0f) == N_DISC) | 
 | 6868 |   || ((plci->NL.Ind &0x0f) == N_DISC_ACK) | 
 | 6869 |   || (((plci->NL.Ind &0x0f) == N_EDATA) | 
 | 6870 |    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI))) | 
 | 6871 |  { | 
 | 6872 |           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND; | 
 | 6873 |  } | 
 | 6874 |       } | 
 | 6875 |       break; | 
 | 6876 |  | 
 | 6877 |     case B3_RTP: | 
 | 6878 |       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)) | 
 | 6879 |       { | 
 | 6880 |         if (plci->NL.RLength != 0) | 
 | 6881 |         { | 
 | 6882 |           info = rtp_info[plci->NL.RBuffer->P[0]]; | 
 | 6883 |           plci->ncpi_buffer[0] = plci->NL.RLength - 1; | 
 | 6884 |           for (i = 1; i < plci->NL.RLength; i++) | 
 | 6885 |             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i]; | 
 | 6886 |         } | 
 | 6887 |       } | 
 | 6888 |       break; | 
 | 6889 |  | 
 | 6890 |     } | 
 | 6891 |     plci->NL.RNR = 2; | 
 | 6892 |   } | 
 | 6893 |   switch(plci->NL.Ind &0x0f) { | 
 | 6894 |   case N_EDATA: | 
 | 6895 |     if ((plci->B3_prot == 4) || (plci->B3_prot == 5)) | 
 | 6896 |     { | 
 | 6897 |       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci], | 
 | 6898 |         ((T30_INFO   *)plci->NL.RBuffer->P)->code)); | 
 | 6899 |       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG); | 
 | 6900 |  | 
 | 6901 |       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) | 
 | 6902 |        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) | 
 | 6903 |        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS) | 
 | 6904 |        && (a->ncci_state[ncci] == OUTG_CON_PENDING) | 
 | 6905 |        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 6906 |        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT)) | 
 | 6907 |       { | 
 | 6908 |         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code; | 
 | 6909 |         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3, | 
 | 6910 |           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer); | 
 | 6911 |         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT; | 
 | 6912 |  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6913 |    fax_send_edata_ack = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6914 |       } | 
 | 6915 |  | 
 | 6916 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | 
 | 6917 |       { | 
 | 6918 |         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code) | 
 | 6919 |         { | 
 | 6920 |         case EDATA_T30_DIS: | 
 | 6921 |           if ((a->ncci_state[ncci] == OUTG_CON_PENDING) | 
 | 6922 |            && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING) | 
 | 6923 |            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 6924 |            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | 
 | 6925 |           { | 
 | 6926 |             a->ncci_state[ncci] = INC_ACT_PENDING; | 
 | 6927 |             if (plci->B3_prot == 4) | 
 | 6928 |               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | 
 | 6929 |             else | 
 | 6930 |               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | 
 | 6931 |             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | 
 | 6932 |           } | 
 | 6933 |           break; | 
 | 6934 |  | 
 | 6935 |         case EDATA_T30_TRAIN_OK: | 
 | 6936 |           if ((a->ncci_state[ncci] == INC_ACT_PENDING) | 
 | 6937 |            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 6938 |            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | 
 | 6939 |           { | 
 | 6940 |             if (plci->B3_prot == 4) | 
 | 6941 |               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | 
 | 6942 |             else | 
 | 6943 |               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | 
 | 6944 |             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | 
 | 6945 |           } | 
 | 6946 |           break; | 
 | 6947 |  | 
 | 6948 |         case EDATA_T30_EOP_CAPI: | 
 | 6949 |           if (a->ncci_state[ncci] == CONNECTED) | 
 | 6950 |           { | 
 | 6951 |             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer); | 
 | 6952 |             a->ncci_state[ncci] = INC_DIS_PENDING; | 
 | 6953 |             plci->ncpi_state = 0; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 6954 |      fax_send_edata_ack = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6955 |           } | 
 | 6956 |           break; | 
 | 6957 |         } | 
 | 6958 |       } | 
 | 6959 |       else | 
 | 6960 |       { | 
 | 6961 |         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code) | 
 | 6962 |         { | 
 | 6963 |         case EDATA_T30_TRAIN_OK: | 
 | 6964 |           if ((a->ncci_state[ncci] == INC_ACT_PENDING) | 
 | 6965 |            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 6966 |            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | 
 | 6967 |           { | 
 | 6968 |             if (plci->B3_prot == 4) | 
 | 6969 |               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | 
 | 6970 |             else | 
 | 6971 |               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | 
 | 6972 |             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | 
 | 6973 |           } | 
 | 6974 |           break; | 
 | 6975 |         } | 
 | 6976 |       } | 
 | 6977 |       if (fax_send_edata_ack) | 
 | 6978 |       { | 
 | 6979 |         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code; | 
 | 6980 |  plci->fax_edata_ack_length = 1; | 
 | 6981 |         start_internal_command (Id, plci, fax_edata_ack_command); | 
 | 6982 |       } | 
 | 6983 |     } | 
 | 6984 |     else | 
 | 6985 |     { | 
 | 6986 |       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci])); | 
 | 6987 |     } | 
 | 6988 |     break; | 
 | 6989 |   case N_CONNECT: | 
 | 6990 |     if (!a->ch_ncci[ch]) | 
 | 6991 |     { | 
 | 6992 |       ncci = get_ncci (plci, ch, 0); | 
 | 6993 |       Id = (Id & 0xffff) | (((dword) ncci) << 16); | 
 | 6994 |     } | 
 | 6995 |     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d", | 
 | 6996 |       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State)); | 
 | 6997 |  | 
 | 6998 |     msg = _CONNECT_B3_I; | 
 | 6999 |     if (a->ncci_state[ncci] == IDLE) | 
 | 7000 |       plci->channels++; | 
 | 7001 |     else if (plci->B3_prot == 1) | 
 | 7002 |       msg = _CONNECT_B3_T90_ACTIVE_I; | 
 | 7003 |  | 
 | 7004 |     a->ncci_state[ncci] = INC_CON_PENDING; | 
 | 7005 |     if(plci->B3_prot == 4) | 
 | 7006 |       sendf(plci->appl,msg,Id,0,"s",""); | 
 | 7007 |     else | 
 | 7008 |       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | 
 | 7009 |     break; | 
 | 7010 |   case N_CONNECT_ACK: | 
 | 7011 |     dbug(1,dprintf("N_connect_Ack")); | 
 | 7012 |     if (plci->internal_command_queue[0] | 
 | 7013 |      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2) | 
 | 7014 |       || (plci->adjust_b_state == ADJUST_B_CONNECT_3) | 
 | 7015 |       || (plci->adjust_b_state == ADJUST_B_CONNECT_4))) | 
 | 7016 |     { | 
 | 7017 |       (*(plci->internal_command_queue[0]))(Id, plci, 0); | 
 | 7018 |       if (!plci->internal_command) | 
 | 7019 |         next_internal_command (Id, plci); | 
 | 7020 |       break; | 
 | 7021 |     } | 
 | 7022 |     msg = _CONNECT_B3_ACTIVE_I; | 
 | 7023 |     if (plci->B3_prot == 1) | 
 | 7024 |     { | 
 | 7025 |       if (a->ncci_state[ncci] != OUTG_CON_PENDING) | 
 | 7026 |         msg = _CONNECT_B3_T90_ACTIVE_I; | 
 | 7027 |       a->ncci_state[ncci] = INC_ACT_PENDING; | 
 | 7028 |       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | 
 | 7029 |     } | 
 | 7030 |     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7)) | 
 | 7031 |     { | 
 | 7032 |       if ((a->ncci_state[ncci] == OUTG_CON_PENDING) | 
 | 7033 |        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 7034 |        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | 
 | 7035 |       { | 
 | 7036 |         a->ncci_state[ncci] = INC_ACT_PENDING; | 
 | 7037 |         if (plci->B3_prot == 4) | 
 | 7038 |           sendf(plci->appl,msg,Id,0,"s",""); | 
 | 7039 |         else | 
 | 7040 |           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | 
 | 7041 |         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | 
 | 7042 |       } | 
 | 7043 |     } | 
 | 7044 |     else | 
 | 7045 |     { | 
 | 7046 |       a->ncci_state[ncci] = INC_ACT_PENDING; | 
 | 7047 |       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | 
 | 7048 |     } | 
 | 7049 |     if (plci->adjust_b_restore) | 
 | 7050 |     { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 7051 |       plci->adjust_b_restore = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7052 |       start_internal_command (Id, plci, adjust_b_restore); | 
 | 7053 |     } | 
 | 7054 |     break; | 
 | 7055 |   case N_DISC: | 
 | 7056 |   case N_DISC_ACK: | 
 | 7057 |     if (plci->internal_command_queue[0] | 
 | 7058 |      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1) | 
 | 7059 |       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2) | 
 | 7060 |       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3))) | 
 | 7061 |     { | 
 | 7062 |       (*(plci->internal_command_queue[0]))(Id, plci, 0); | 
 | 7063 |       if (!plci->internal_command) | 
 | 7064 |         next_internal_command (Id, plci); | 
 | 7065 |     } | 
 | 7066 |     ncci_state = a->ncci_state[ncci]; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 7067 |     ncci_remove (plci, ncci, false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7068 |  | 
 | 7069 |         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */ | 
 | 7070 |         /* channel, so we cannot store the state in ncci_state! The */ | 
 | 7071 |         /* information which channel we received a N_DISC is thus   */ | 
 | 7072 |         /* stored in the inc_dis_ncci_table buffer.                 */ | 
 | 7073 |     for(i=0; plci->inc_dis_ncci_table[i]; i++); | 
 | 7074 |     plci->inc_dis_ncci_table[i] = (byte) ncci; | 
 | 7075 |  | 
 | 7076 |       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */ | 
 | 7077 |     if (!plci->channels | 
 | 7078 |      && (plci->B1_resource == 16) | 
 | 7079 |      && (plci->State <= CONNECTED)) | 
 | 7080 |     { | 
 | 7081 |       len = 9; | 
 | 7082 |       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400; | 
 | 7083 |       PUT_WORD (&plci->ncpi_buffer[1], i); | 
 | 7084 |       PUT_WORD (&plci->ncpi_buffer[3], 0); | 
 | 7085 |       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format; | 
 | 7086 |       PUT_WORD (&plci->ncpi_buffer[5], i); | 
 | 7087 |       PUT_WORD (&plci->ncpi_buffer[7], 0); | 
 | 7088 |       plci->ncpi_buffer[len] = 0; | 
 | 7089 |       plci->ncpi_buffer[0] = len; | 
 | 7090 |       if(plci->B3_prot == 4) | 
 | 7091 |         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s",""); | 
 | 7092 |       else | 
 | 7093 |       { | 
 | 7094 |  | 
 | 7095 |         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) | 
 | 7096 |           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | 
 | 7097 |         { | 
 | 7098 |           plci->ncpi_buffer[++len] = 0; | 
 | 7099 |           plci->ncpi_buffer[++len] = 0; | 
 | 7100 |           plci->ncpi_buffer[++len] = 0; | 
 | 7101 |           plci->ncpi_buffer[0] = len; | 
 | 7102 |         } | 
 | 7103 |  | 
 | 7104 |         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer); | 
 | 7105 |       } | 
 | 7106 |       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer); | 
 | 7107 |       plci->ncpi_state = 0; | 
 | 7108 |       sig_req(plci,HANGUP,0); | 
 | 7109 |       send_req(plci); | 
 | 7110 |       plci->State = OUTG_DIS_PENDING; | 
 | 7111 |       /* disc here */ | 
 | 7112 |     } | 
 | 7113 |     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | 
 | 7114 |      && ((plci->B3_prot == 4) || (plci->B3_prot == 5)) | 
 | 7115 |      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE))) | 
 | 7116 |     { | 
 | 7117 |       if (ncci_state == IDLE) | 
 | 7118 |       { | 
 | 7119 |         if (plci->channels) | 
 | 7120 |           plci->channels--; | 
 | 7121 |         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){ | 
 | 7122 |           if(plci->State == SUSPENDING){ | 
 | 7123 |             sendf(plci->appl, | 
 | 7124 |                   _FACILITY_I, | 
 | 7125 |                   Id & 0xffffL, | 
 | 7126 |                   0, | 
 | 7127 |                   "ws", (word)3, "\x03\x04\x00\x00"); | 
 | 7128 |             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0); | 
 | 7129 |           } | 
 | 7130 |           plci_remove(plci); | 
 | 7131 |           plci->State=IDLE; | 
 | 7132 |         } | 
 | 7133 |       } | 
 | 7134 |     } | 
 | 7135 |     else if (plci->channels) | 
 | 7136 |     { | 
 | 7137 |       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer); | 
 | 7138 |       plci->ncpi_state = 0; | 
 | 7139 |       if ((ncci_state == OUTG_REJ_PENDING) | 
 | 7140 |        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))) | 
 | 7141 |       { | 
 | 7142 |         sig_req(plci,HANGUP,0); | 
 | 7143 |         send_req(plci); | 
 | 7144 |         plci->State = OUTG_DIS_PENDING; | 
 | 7145 |       } | 
 | 7146 |     } | 
 | 7147 |     break; | 
 | 7148 |   case N_RESET: | 
 | 7149 |     a->ncci_state[ncci] = INC_RES_PENDING; | 
 | 7150 |     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer); | 
 | 7151 |     break; | 
 | 7152 |   case N_RESET_ACK: | 
 | 7153 |     a->ncci_state[ncci] = CONNECTED; | 
 | 7154 |     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer); | 
 | 7155 |     break; | 
 | 7156 |  | 
 | 7157 |   case N_UDATA: | 
 | 7158 |     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f)))) | 
 | 7159 |     { | 
| Andrew Morton | d3c8bdf | 2007-05-23 13:58:22 -0700 | [diff] [blame] | 7160 |       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7161 |       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE; | 
 | 7162 |       plci->NL.R = plci->RData; | 
 | 7163 |       plci->NL.RNum = 1; | 
 | 7164 |       return; | 
 | 7165 |     } | 
 | 7166 |   case N_BDATA: | 
 | 7167 |   case N_DATA: | 
 | 7168 |     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */ | 
 | 7169 |      || (a->ncci_state[ncci] == IDLE) | 
 | 7170 |      || (a->ncci_state[ncci] == INC_DIS_PENDING)) | 
 | 7171 |     { | 
 | 7172 |       plci->NL.RNR = 2; | 
 | 7173 |       break; | 
 | 7174 |     } | 
 | 7175 |     if ((a->ncci_state[ncci] != CONNECTED) | 
 | 7176 |      && (a->ncci_state[ncci] != OUTG_DIS_PENDING) | 
 | 7177 |      && (a->ncci_state[ncci] != OUTG_REJ_PENDING)) | 
 | 7178 |     { | 
 | 7179 |       dbug(1,dprintf("flow control")); | 
 | 7180 |       plci->NL.RNR = 1; /* flow control  */ | 
 | 7181 |       channel_x_off (plci, ch, 0); | 
 | 7182 |       break; | 
 | 7183 |     } | 
 | 7184 |  | 
 | 7185 |     NCCIcode = ncci | (((word)a->Id) << 8); | 
 | 7186 |  | 
 | 7187 |                 /* count all buffers within the Application pool    */ | 
 | 7188 |                 /* belonging to the same NCCI. If this is below the */ | 
 | 7189 |                 /* number of buffers available per NCCI we accept   */ | 
 | 7190 |                 /* this packet, otherwise we reject it              */ | 
 | 7191 |     count = 0; | 
 | 7192 |     Num = 0xffff; | 
 | 7193 |     for(i=0; i<APPLptr->MaxBuffer; i++) { | 
 | 7194 |       if(NCCIcode==APPLptr->DataNCCI[i]) count++; | 
 | 7195 |       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i; | 
 | 7196 |     } | 
 | 7197 |  | 
 | 7198 |     if(count>=APPLptr->MaxNCCIData || Num==0xffff) | 
 | 7199 |     { | 
 | 7200 |       dbug(3,dprintf("Flow-Control")); | 
 | 7201 |       plci->NL.RNR = 1; | 
 | 7202 |       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>= | 
 | 7203 |        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000)) | 
 | 7204 |       { | 
 | 7205 |         plci->NL.RNR = 2; | 
 | 7206 |         dbug(3,dprintf("DiscardData")); | 
 | 7207 |       } else { | 
 | 7208 |         channel_x_off (plci, ch, 0); | 
 | 7209 |       } | 
 | 7210 |       break; | 
 | 7211 |     } | 
 | 7212 |     else | 
 | 7213 |     { | 
 | 7214 |       APPLptr->NCCIDataFlowCtrlTimer = 0; | 
 | 7215 |     } | 
 | 7216 |  | 
 | 7217 |     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num); | 
 | 7218 |     if(!plci->RData[0].P) { | 
 | 7219 |       plci->NL.RNR = 1; | 
 | 7220 |       channel_x_off (plci, ch, 0); | 
 | 7221 |       break; | 
 | 7222 |     } | 
 | 7223 |  | 
 | 7224 |     APPLptr->DataNCCI[Num] = NCCIcode; | 
 | 7225 |     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4); | 
 | 7226 |     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer)); | 
 | 7227 |  | 
 | 7228 |     plci->RNum = Num; | 
 | 7229 |     plci->RFlags = plci->NL.Ind>>4; | 
 | 7230 |     plci->RData[0].PLength = APPLptr->MaxDataLength; | 
 | 7231 |     plci->NL.R = plci->RData; | 
 | 7232 |     if ((plci->NL.RLength != 0) | 
 | 7233 |      && ((plci->B2_prot == B2_V120_ASYNC) | 
 | 7234 |       || (plci->B2_prot == B2_V120_ASYNC_V42BIS) | 
 | 7235 |       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))) | 
 | 7236 |     { | 
 | 7237 |       plci->RData[1].P = plci->RData[0].P; | 
 | 7238 |       plci->RData[1].PLength = plci->RData[0].PLength; | 
| Jiri Slaby | 1ea7084 | 2009-11-04 08:28:12 -0800 | [diff] [blame] | 7239 |       plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7240 |       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1)) | 
 | 7241 |         plci->RData[0].PLength = 1; | 
 | 7242 |       else | 
 | 7243 |         plci->RData[0].PLength = 2; | 
 | 7244 |       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT) | 
 | 7245 |         plci->RFlags |= 0x0010; | 
 | 7246 |       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)) | 
 | 7247 |         plci->RFlags |= 0x8000; | 
 | 7248 |       plci->NL.RNum = 2; | 
 | 7249 |     } | 
 | 7250 |     else | 
 | 7251 |     { | 
 | 7252 |       if((plci->NL.Ind &0x0f)==N_UDATA) | 
 | 7253 |         plci->RFlags |= 0x0010; | 
 | 7254 |  | 
 | 7255 |       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA)) | 
 | 7256 |         plci->RFlags |= 0x0001; | 
 | 7257 |  | 
 | 7258 |       plci->NL.RNum = 1; | 
 | 7259 |     } | 
 | 7260 |     break; | 
 | 7261 |   case N_DATA_ACK: | 
 | 7262 |     data_ack (plci, ch); | 
 | 7263 |     break; | 
 | 7264 |   default: | 
 | 7265 |     plci->NL.RNR = 2; | 
 | 7266 |     break; | 
 | 7267 |   } | 
 | 7268 | } | 
 | 7269 |  | 
 | 7270 | /*------------------------------------------------------------------*/ | 
 | 7271 | /* find a free PLCI                                                 */ | 
 | 7272 | /*------------------------------------------------------------------*/ | 
 | 7273 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 7274 | static word get_plci(DIVA_CAPI_ADAPTER *a) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7275 | { | 
 | 7276 |   word i,j; | 
 | 7277 |   PLCI   * plci; | 
 | 7278 |  | 
 | 7279 |   dump_plcis (a); | 
 | 7280 |   for(i=0;i<a->max_plci && a->plci[i].Id;i++); | 
 | 7281 |   if(i==a->max_plci) { | 
 | 7282 |     dbug(1,dprintf("get_plci: out of PLCIs")); | 
 | 7283 |     return 0; | 
 | 7284 |   } | 
 | 7285 |   plci = &a->plci[i]; | 
 | 7286 |   plci->Id = (byte)(i+1); | 
 | 7287 |  | 
 | 7288 |   plci->Sig.Id = 0; | 
 | 7289 |   plci->NL.Id = 0; | 
 | 7290 |   plci->sig_req = 0; | 
 | 7291 |   plci->nl_req = 0; | 
 | 7292 |  | 
 | 7293 |   plci->appl = NULL; | 
 | 7294 |   plci->relatedPTYPLCI = NULL; | 
 | 7295 |   plci->State = IDLE; | 
 | 7296 |   plci->SuppState = IDLE; | 
 | 7297 |   plci->channels = 0; | 
 | 7298 |   plci->tel = 0; | 
 | 7299 |   plci->B1_resource = 0; | 
 | 7300 |   plci->B2_prot = 0; | 
 | 7301 |   plci->B3_prot = 0; | 
 | 7302 |  | 
 | 7303 |   plci->command = 0; | 
 | 7304 |   plci->m_command = 0; | 
 | 7305 |   init_internal_command_queue (plci); | 
 | 7306 |   plci->number = 0; | 
 | 7307 |   plci->req_in_start = 0; | 
 | 7308 |   plci->req_in = 0; | 
 | 7309 |   plci->req_out = 0; | 
 | 7310 |   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE; | 
 | 7311 |   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | 
 | 7312 |   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | 
 | 7313 |  | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 7314 |   plci->data_sent = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7315 |   plci->send_disc = 0; | 
 | 7316 |   plci->sig_global_req = 0; | 
 | 7317 |   plci->sig_remove_id = 0; | 
 | 7318 |   plci->nl_global_req = 0; | 
 | 7319 |   plci->nl_remove_id = 0; | 
 | 7320 |   plci->adv_nl = 0; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 7321 |   plci->manufacturer = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7322 |   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | 
 | 7323 |   plci->spoofed_msg = 0; | 
 | 7324 |   plci->ptyState = 0; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 7325 |   plci->cr_enquiry = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7326 |   plci->hangup_flow_ctrl_timer = 0; | 
 | 7327 |  | 
 | 7328 |   plci->ncci_ring_list = 0; | 
 | 7329 |   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0; | 
 | 7330 |   clear_c_ind_mask (plci); | 
 | 7331 |   set_group_ind_mask (plci); | 
 | 7332 |   plci->fax_connect_info_length = 0; | 
 | 7333 |   plci->nsf_control_bits = 0; | 
 | 7334 |   plci->ncpi_state = 0x00; | 
 | 7335 |   plci->ncpi_buffer[0] = 0; | 
 | 7336 |  | 
 | 7337 |   plci->requested_options_conn = 0; | 
 | 7338 |   plci->requested_options = 0; | 
 | 7339 |   plci->notifiedcall = 0; | 
 | 7340 |   plci->vswitchstate = 0; | 
 | 7341 |   plci->vsprot = 0; | 
 | 7342 |   plci->vsprotdialect = 0; | 
 | 7343 |   init_b1_config (plci); | 
 | 7344 |   dbug(1,dprintf("get_plci(%x)",plci->Id)); | 
 | 7345 |   return i+1; | 
 | 7346 | } | 
 | 7347 |  | 
 | 7348 | /*------------------------------------------------------------------*/ | 
 | 7349 | /* put a parameter in the parameter buffer                          */ | 
 | 7350 | /*------------------------------------------------------------------*/ | 
 | 7351 |  | 
 | 7352 | static void add_p(PLCI   * plci, byte code, byte   * p) | 
 | 7353 | { | 
 | 7354 |   word p_length; | 
 | 7355 |  | 
 | 7356 |   p_length = 0; | 
 | 7357 |   if(p) p_length = p[0]; | 
 | 7358 |   add_ie(plci, code, p, p_length); | 
 | 7359 | } | 
 | 7360 |  | 
 | 7361 | /*------------------------------------------------------------------*/ | 
 | 7362 | /* put a structure in the parameter buffer                          */ | 
 | 7363 | /*------------------------------------------------------------------*/ | 
 | 7364 | static void add_s(PLCI   * plci, byte code, API_PARSE * p) | 
 | 7365 | { | 
 | 7366 |   if(p) add_ie(plci, code, p->info, (word)p->length); | 
 | 7367 | } | 
 | 7368 |  | 
 | 7369 | /*------------------------------------------------------------------*/ | 
 | 7370 | /* put multiple structures in the parameter buffer                  */ | 
 | 7371 | /*------------------------------------------------------------------*/ | 
 | 7372 | static void add_ss(PLCI   * plci, byte code, API_PARSE * p) | 
 | 7373 | { | 
 | 7374 |   byte i; | 
 | 7375 |  | 
 | 7376 |   if(p){ | 
 | 7377 |     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length)); | 
 | 7378 |     for(i=2;i<(byte)p->length;i+=p->info[i]+2){ | 
 | 7379 |       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i])); | 
 | 7380 |       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]); | 
 | 7381 |     } | 
 | 7382 |   } | 
 | 7383 | } | 
 | 7384 |  | 
 | 7385 | /*------------------------------------------------------------------*/ | 
 | 7386 | /* return the channel number sent by the application in a esc_chi   */ | 
 | 7387 | /*------------------------------------------------------------------*/ | 
 | 7388 | static byte getChannel(API_PARSE * p) | 
 | 7389 | { | 
 | 7390 |   byte i; | 
 | 7391 |  | 
 | 7392 |   if(p){ | 
 | 7393 |     for(i=2;i<(byte)p->length;i+=p->info[i]+2){ | 
 | 7394 |       if(p->info[i]==2){ | 
 | 7395 |         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]); | 
 | 7396 |       } | 
 | 7397 |     } | 
 | 7398 |   } | 
 | 7399 |   return 0; | 
 | 7400 | } | 
 | 7401 |  | 
 | 7402 |  | 
 | 7403 | /*------------------------------------------------------------------*/ | 
 | 7404 | /* put an information element in the parameter buffer               */ | 
 | 7405 | /*------------------------------------------------------------------*/ | 
 | 7406 |  | 
 | 7407 | static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length) | 
 | 7408 | { | 
 | 7409 |   word i; | 
 | 7410 |  | 
 | 7411 |   if(!(code &0x80) && !p_length) return; | 
 | 7412 |  | 
 | 7413 |   if(plci->req_in==plci->req_in_start) { | 
 | 7414 |     plci->req_in +=2; | 
 | 7415 |   } | 
 | 7416 |   else { | 
 | 7417 |     plci->req_in--; | 
 | 7418 |   } | 
 | 7419 |   plci->RBuffer[plci->req_in++] = code; | 
 | 7420 |  | 
 | 7421 |   if(p) { | 
 | 7422 |     plci->RBuffer[plci->req_in++] = (byte)p_length; | 
 | 7423 |     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i]; | 
 | 7424 |   } | 
 | 7425 |  | 
 | 7426 |   plci->RBuffer[plci->req_in++] = 0; | 
 | 7427 | } | 
 | 7428 |  | 
 | 7429 | /*------------------------------------------------------------------*/ | 
 | 7430 | /* put a unstructured data into the buffer                          */ | 
 | 7431 | /*------------------------------------------------------------------*/ | 
 | 7432 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 7433 | static void add_d(PLCI *plci, word length, byte *p) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7434 | { | 
 | 7435 |   word i; | 
 | 7436 |  | 
 | 7437 |   if(plci->req_in==plci->req_in_start) { | 
 | 7438 |     plci->req_in +=2; | 
 | 7439 |   } | 
 | 7440 |   else { | 
 | 7441 |     plci->req_in--; | 
 | 7442 |   } | 
 | 7443 |   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i]; | 
 | 7444 | } | 
 | 7445 |  | 
 | 7446 | /*------------------------------------------------------------------*/ | 
 | 7447 | /* put parameters from the Additional Info parameter in the         */ | 
 | 7448 | /* parameter buffer                                                 */ | 
 | 7449 | /*------------------------------------------------------------------*/ | 
 | 7450 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 7451 | static void add_ai(PLCI *plci, API_PARSE *ai) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7452 | { | 
 | 7453 |   word i; | 
 | 7454 |     API_PARSE ai_parms[5]; | 
 | 7455 |  | 
 | 7456 |   for(i=0;i<5;i++) ai_parms[i].length = 0; | 
 | 7457 |  | 
 | 7458 |   if(!ai->length) | 
 | 7459 |     return; | 
 | 7460 |   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms)) | 
 | 7461 |     return; | 
 | 7462 |  | 
 | 7463 |   add_s (plci,KEY,&ai_parms[1]); | 
 | 7464 |   add_s (plci,UUI,&ai_parms[2]); | 
 | 7465 |   add_ss(plci,FTY,&ai_parms[3]); | 
 | 7466 | } | 
 | 7467 |  | 
 | 7468 | /*------------------------------------------------------------------*/ | 
 | 7469 | /* put parameter for b1 protocol in the parameter buffer            */ | 
 | 7470 | /*------------------------------------------------------------------*/ | 
 | 7471 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 7472 | static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info, | 
 | 7473 | 		   word b1_facilities) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7474 | { | 
 | 7475 |     API_PARSE bp_parms[8]; | 
 | 7476 |     API_PARSE mdm_cfg[9]; | 
 | 7477 |     API_PARSE global_config[2]; | 
 | 7478 |     byte cai[256]; | 
 | 7479 |   byte resource[] = {5,9,13,12,16,39,9,17,17,18}; | 
 | 7480 |   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08"; | 
 | 7481 |   word i; | 
 | 7482 |  | 
 | 7483 |     API_PARSE mdm_cfg_v18[4]; | 
 | 7484 |   word j, n, w; | 
 | 7485 |   dword d; | 
 | 7486 |  | 
 | 7487 |  | 
 | 7488 |   for(i=0;i<8;i++) bp_parms[i].length = 0; | 
 | 7489 |   for(i=0;i<2;i++) global_config[i].length = 0; | 
 | 7490 |  | 
 | 7491 |   dbug(1,dprintf("add_b1")); | 
 | 7492 |   api_save_msg(bp, "s", &plci->B_protocol); | 
 | 7493 |  | 
 | 7494 |   if(b_channel_info==2){ | 
 | 7495 |     plci->B1_resource = 0; | 
 | 7496 |     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities); | 
 | 7497 |     add_p(plci, CAI, "\x01\x00"); | 
 | 7498 |     dbug(1,dprintf("Cai=1,0 (no resource)")); | 
 | 7499 |     return 0; | 
 | 7500 |   } | 
 | 7501 |  | 
 | 7502 |   if(plci->tel == CODEC_PERMANENT) return 0; | 
 | 7503 |   else if(plci->tel == CODEC){ | 
 | 7504 |     plci->B1_resource = 1; | 
 | 7505 |     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities); | 
 | 7506 |     add_p(plci, CAI, "\x01\x01"); | 
 | 7507 |     dbug(1,dprintf("Cai=1,1 (Codec)")); | 
 | 7508 |     return 0; | 
 | 7509 |   } | 
 | 7510 |   else if(plci->tel == ADV_VOICE){ | 
 | 7511 |     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE)); | 
 | 7512 |     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE)); | 
 | 7513 |     voice_cai[1] = plci->B1_resource; | 
 | 7514 |     PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength); | 
 | 7515 |     add_p(plci, CAI, voice_cai); | 
 | 7516 |     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1])); | 
 | 7517 |     return 0; | 
 | 7518 |   } | 
 | 7519 |   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER); | 
 | 7520 |   if (plci->call_dir & CALL_DIR_OUT) | 
 | 7521 |     plci->call_dir |= CALL_DIR_ORIGINATE; | 
 | 7522 |   else if (plci->call_dir & CALL_DIR_IN) | 
 | 7523 |     plci->call_dir |= CALL_DIR_ANSWER; | 
 | 7524 |  | 
 | 7525 |   if(!bp->length){ | 
 | 7526 |     plci->B1_resource = 0x5; | 
 | 7527 |     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities); | 
 | 7528 |     add_p(plci, CAI, "\x01\x05"); | 
 | 7529 |     return 0; | 
 | 7530 |   } | 
 | 7531 |  | 
 | 7532 |   dbug(1,dprintf("b_prot_len=%d",(word)bp->length)); | 
 | 7533 |   if(bp->length>256) return _WRONG_MESSAGE_FORMAT; | 
 | 7534 |   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms)) | 
 | 7535 |   { | 
 | 7536 |     bp_parms[6].length = 0; | 
 | 7537 |     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms)) | 
 | 7538 |     { | 
 | 7539 |       dbug(1,dprintf("b-form.!")); | 
 | 7540 |       return _WRONG_MESSAGE_FORMAT; | 
 | 7541 |     } | 
 | 7542 |   } | 
 | 7543 |   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms)) | 
 | 7544 |   { | 
 | 7545 |     dbug(1,dprintf("b-form.!")); | 
 | 7546 |     return _WRONG_MESSAGE_FORMAT; | 
 | 7547 |   } | 
 | 7548 |  | 
 | 7549 |   if(bp_parms[6].length) | 
 | 7550 |   { | 
 | 7551 |     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config)) | 
 | 7552 |     { | 
 | 7553 |       return _WRONG_MESSAGE_FORMAT; | 
 | 7554 |     } | 
 | 7555 |     switch(GET_WORD(global_config[0].info)) | 
 | 7556 |     { | 
 | 7557 |     case 1: | 
 | 7558 |       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE; | 
 | 7559 |       break; | 
 | 7560 |     case 2: | 
 | 7561 |       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER; | 
 | 7562 |       break; | 
 | 7563 |     } | 
 | 7564 |   } | 
 | 7565 |   dbug(1,dprintf("call_dir=%04x", plci->call_dir)); | 
 | 7566 |  | 
 | 7567 |  | 
 | 7568 |   if ((GET_WORD(bp_parms[0].info) == B1_RTP) | 
 | 7569 |    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP))) | 
 | 7570 |   { | 
 | 7571 |     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | 
 | 7572 |     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | 
 | 7573 |     cai[1] = plci->B1_resource; | 
 | 7574 |     cai[2] = 0; | 
 | 7575 |     cai[3] = 0; | 
 | 7576 |     cai[4] = 0; | 
 | 7577 |     PUT_WORD(&cai[5],plci->appl->MaxDataLength); | 
 | 7578 |     for (i = 0; i < bp_parms[3].length; i++) | 
 | 7579 |       cai[7+i] = bp_parms[3].info[1+i]; | 
 | 7580 |     cai[0] = 6 + bp_parms[3].length; | 
 | 7581 |     add_p(plci, CAI, cai); | 
 | 7582 |     return 0; | 
 | 7583 |   } | 
 | 7584 |  | 
 | 7585 |  | 
 | 7586 |   if ((GET_WORD(bp_parms[0].info) == B1_PIAFS) | 
 | 7587 |    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS))) | 
 | 7588 |   { | 
 | 7589 |     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | 
 | 7590 |     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | 
 | 7591 |     cai[1] = plci->B1_resource; | 
 | 7592 |     cai[2] = 0; | 
 | 7593 |     cai[3] = 0; | 
 | 7594 |     cai[4] = 0; | 
 | 7595 |     PUT_WORD(&cai[5],plci->appl->MaxDataLength); | 
 | 7596 |     cai[0] = 6; | 
 | 7597 |     add_p(plci, CAI, cai); | 
 | 7598 |     return 0; | 
 | 7599 |   } | 
 | 7600 |  | 
 | 7601 |  | 
 | 7602 |   if ((GET_WORD(bp_parms[0].info) >= 32) | 
 | 7603 |    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols) | 
 | 7604 |     && ((GET_WORD(bp_parms[0].info) != 3) | 
 | 7605 |      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols) | 
 | 7606 |      || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000))))) | 
 | 7607 |   { | 
 | 7608 |     return _B1_NOT_SUPPORTED; | 
 | 7609 |   } | 
 | 7610 |   plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)], | 
 | 7611 |     (word)(b1_facilities & ~B1_FACILITY_VOICE)); | 
 | 7612 |   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | 
 | 7613 |   cai[0] = 6; | 
 | 7614 |   cai[1] = plci->B1_resource; | 
 | 7615 |   for (i=2;i<sizeof(cai);i++) cai[i] = 0; | 
 | 7616 |  | 
 | 7617 |   if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) | 
 | 7618 |    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC) | 
 | 7619 |    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)) | 
 | 7620 |   { /* B1 - modem */ | 
 | 7621 |     for (i=0;i<7;i++) mdm_cfg[i].length = 0; | 
 | 7622 |  | 
 | 7623 |     if (bp_parms[3].length) | 
 | 7624 |     { | 
 | 7625 |       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg)) | 
 | 7626 |       { | 
 | 7627 |         return (_WRONG_MESSAGE_FORMAT); | 
 | 7628 |       } | 
 | 7629 |          | 
 | 7630 |       cai[2] = 0; /* Bit rate for adaptation */ | 
 | 7631 |  | 
 | 7632 |       dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info))); | 
 | 7633 |  | 
 | 7634 |       PUT_WORD (&cai[13], 0);                          /* Min Tx speed */ | 
 | 7635 |       PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */ | 
 | 7636 |       PUT_WORD (&cai[17], 0);                          /* Min Rx speed */ | 
 | 7637 |       PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */ | 
 | 7638 |  | 
 | 7639 |       cai[3] = 0; /* Async framing parameters */ | 
 | 7640 |       switch (GET_WORD (mdm_cfg[2].info)) | 
 | 7641 |       {       /* Parity     */ | 
 | 7642 |       case 1: /* odd parity */ | 
 | 7643 |         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD); | 
 | 7644 |         dbug(1,dprintf("MDM: odd parity")); | 
 | 7645 |         break; | 
 | 7646 |  | 
 | 7647 |       case 2: /* even parity */ | 
 | 7648 |         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN); | 
 | 7649 |         dbug(1,dprintf("MDM: even parity")); | 
 | 7650 |         break; | 
 | 7651 |  | 
 | 7652 |       default: | 
 | 7653 |         dbug(1,dprintf("MDM: no parity")); | 
 | 7654 |         break; | 
 | 7655 |       } | 
 | 7656 |  | 
 | 7657 |       switch (GET_WORD (mdm_cfg[3].info)) | 
 | 7658 |       {       /* stop bits   */ | 
 | 7659 |       case 1: /* 2 stop bits */ | 
 | 7660 |         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS; | 
 | 7661 |         dbug(1,dprintf("MDM: 2 stop bits")); | 
 | 7662 |         break; | 
 | 7663 |  | 
 | 7664 |       default: | 
 | 7665 |         dbug(1,dprintf("MDM: 1 stop bit")); | 
 | 7666 |         break; | 
 | 7667 |       } | 
 | 7668 |  | 
 | 7669 |       switch (GET_WORD (mdm_cfg[1].info)) | 
 | 7670 |       {     /* char length */ | 
 | 7671 |       case 5: | 
 | 7672 |         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5; | 
 | 7673 |         dbug(1,dprintf("MDM: 5 bits")); | 
 | 7674 |         break; | 
 | 7675 |  | 
 | 7676 |       case 6: | 
 | 7677 |         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6; | 
 | 7678 |         dbug(1,dprintf("MDM: 6 bits")); | 
 | 7679 |         break; | 
 | 7680 |  | 
 | 7681 |       case 7: | 
 | 7682 |         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7; | 
 | 7683 |         dbug(1,dprintf("MDM: 7 bits")); | 
 | 7684 |         break; | 
 | 7685 |  | 
 | 7686 |       default: | 
 | 7687 |         dbug(1,dprintf("MDM: 8 bits")); | 
 | 7688 |         break; | 
 | 7689 |       } | 
 | 7690 |  | 
 | 7691 |       cai[7] = 0; /* Line taking options */ | 
 | 7692 |       cai[8] = 0; /* Modulation negotiation options */ | 
 | 7693 |       cai[9] = 0; /* Modulation options */ | 
 | 7694 |  | 
 | 7695 |       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0)) | 
 | 7696 |       { | 
 | 7697 |         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION; | 
 | 7698 |         dbug(1, dprintf("MDM: Reverse direction")); | 
 | 7699 |       } | 
 | 7700 |  | 
 | 7701 |       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN) | 
 | 7702 |       { | 
 | 7703 |         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN; | 
 | 7704 |         dbug(1, dprintf("MDM: Disable retrain")); | 
 | 7705 |       } | 
 | 7706 |  | 
 | 7707 |       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE) | 
 | 7708 |       { | 
 | 7709 |         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE; | 
 | 7710 |         dbug(1, dprintf("MDM: Disable ring tone")); | 
 | 7711 |       } | 
 | 7712 |  | 
 | 7713 |       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800) | 
 | 7714 |       { | 
 | 7715 |         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ; | 
 | 7716 |         dbug(1, dprintf("MDM: 1800 guard tone")); | 
 | 7717 |       } | 
 | 7718 |       else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 ) | 
 | 7719 |       { | 
 | 7720 |         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ; | 
 | 7721 |         dbug(1, dprintf("MDM: 550 guard tone")); | 
 | 7722 |       } | 
 | 7723 |  | 
 | 7724 |       if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100) | 
 | 7725 |       { | 
 | 7726 |         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100; | 
 | 7727 |         dbug(1, dprintf("MDM: V100")); | 
 | 7728 |       } | 
 | 7729 |       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS) | 
 | 7730 |       { | 
 | 7731 |         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS; | 
 | 7732 |         dbug(1, dprintf("MDM: IN CLASS")); | 
 | 7733 |       } | 
 | 7734 |       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED) | 
 | 7735 |       { | 
 | 7736 |         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED; | 
 | 7737 |         dbug(1, dprintf("MDM: DISABLED")); | 
 | 7738 |       } | 
 | 7739 |       cai[0] = 20; | 
 | 7740 |  | 
 | 7741 |       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18)) | 
 | 7742 |        && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */ | 
 | 7743 |       { | 
 | 7744 |         plci->requested_options |= 1L << PRIVATE_V18; | 
 | 7745 |       } | 
 | 7746 |       if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */ | 
 | 7747 |         plci->requested_options |= 1L << PRIVATE_VOWN; | 
 | 7748 |  | 
 | 7749 |       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | 
 | 7750 |         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN))) | 
 | 7751 |       { | 
 | 7752 |         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg)) | 
 | 7753 |         { | 
 | 7754 |           i = 27; | 
 | 7755 |           if (mdm_cfg[6].length >= 4) | 
 | 7756 |           { | 
 | 7757 |             d = GET_DWORD(&mdm_cfg[6].info[1]); | 
 | 7758 |             cai[7] |= (byte) d;          /* line taking options */ | 
 | 7759 |             cai[9] |= (byte)(d >> 8);    /* modulation options */ | 
 | 7760 |             cai[++i] = (byte)(d >> 16);  /* vown modulation options */ | 
 | 7761 |             cai[++i] = (byte)(d >> 24); | 
 | 7762 |             if (mdm_cfg[6].length >= 8) | 
 | 7763 |             { | 
 | 7764 |               d = GET_DWORD(&mdm_cfg[6].info[5]); | 
 | 7765 |               cai[10] |= (byte) d;        /* disabled modulations mask */ | 
 | 7766 |               cai[11] |= (byte)(d >> 8); | 
 | 7767 |               if (mdm_cfg[6].length >= 12) | 
 | 7768 |               { | 
 | 7769 |                 d = GET_DWORD(&mdm_cfg[6].info[9]); | 
 | 7770 |                 cai[12] = (byte) d;          /* enabled modulations mask */ | 
 | 7771 |                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */ | 
 | 7772 |                 cai[++i] = (byte)(d >> 16); | 
 | 7773 |                 cai[++i] = (byte)(d >> 24); | 
 | 7774 |                 cai[++i] = 0; | 
 | 7775 |                 if (mdm_cfg[6].length >= 14) | 
 | 7776 |                 { | 
 | 7777 |                   w = GET_WORD(&mdm_cfg[6].info[13]); | 
 | 7778 |                   if (w != 0) | 
 | 7779 |                     PUT_WORD(&cai[13], w);  /* min tx speed */ | 
 | 7780 |                   if (mdm_cfg[6].length >= 16) | 
 | 7781 |                   { | 
 | 7782 |                     w = GET_WORD(&mdm_cfg[6].info[15]); | 
 | 7783 |                     if (w != 0) | 
 | 7784 |                       PUT_WORD(&cai[15], w);  /* max tx speed */ | 
 | 7785 |                     if (mdm_cfg[6].length >= 18) | 
 | 7786 |                     { | 
 | 7787 |                       w = GET_WORD(&mdm_cfg[6].info[17]); | 
 | 7788 |                       if (w != 0) | 
 | 7789 |                         PUT_WORD(&cai[17], w);  /* min rx speed */ | 
 | 7790 |                       if (mdm_cfg[6].length >= 20) | 
 | 7791 |                       { | 
 | 7792 |                         w = GET_WORD(&mdm_cfg[6].info[19]); | 
 | 7793 |                         if (w != 0) | 
 | 7794 |                           PUT_WORD(&cai[19], w);  /* max rx speed */ | 
 | 7795 |                         if (mdm_cfg[6].length >= 22) | 
 | 7796 |                         { | 
 | 7797 |                           w = GET_WORD(&mdm_cfg[6].info[21]); | 
 | 7798 |                           cai[23] = (byte)(-((short) w));  /* transmit level */ | 
 | 7799 |                           if (mdm_cfg[6].length >= 24) | 
 | 7800 |                           { | 
 | 7801 |                             w = GET_WORD(&mdm_cfg[6].info[23]); | 
 | 7802 |                             cai[22] |= (byte) w;        /* info options mask */ | 
 | 7803 |                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */ | 
 | 7804 |                           } | 
 | 7805 |                         } | 
 | 7806 |                       } | 
 | 7807 |                     } | 
 | 7808 |                   } | 
 | 7809 |                 } | 
 | 7810 |               } | 
 | 7811 |             } | 
 | 7812 |           } | 
 | 7813 |           cai[27] = i - 27; | 
 | 7814 |           i++; | 
 | 7815 |           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg)) | 
 | 7816 |           { | 
 | 7817 |             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18)) | 
 | 7818 |             { | 
 | 7819 |               for (n = 0; n < 3; n++) | 
 | 7820 |               { | 
 | 7821 |                 cai[i] = (byte)(mdm_cfg_v18[n].length); | 
 | 7822 |                 for (j = 1; j < ((word)(cai[i] + 1)); j++) | 
 | 7823 |                   cai[i+j] = mdm_cfg_v18[n].info[j]; | 
 | 7824 |                 i += cai[i] + 1; | 
 | 7825 |               } | 
 | 7826 |             } | 
 | 7827 |           } | 
 | 7828 |           cai[0] = (byte)(i - 1); | 
 | 7829 |         } | 
 | 7830 |       } | 
 | 7831 |  | 
 | 7832 |     } | 
 | 7833 |   } | 
 | 7834 |   if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */ | 
 | 7835 |      GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */ | 
 | 7836 |   { | 
 | 7837 |     if(bp_parms[3].length){ | 
 | 7838 |       dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1]))); | 
 | 7839 |       switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */ | 
 | 7840 |         case 0: | 
 | 7841 |         case 56000: | 
 | 7842 |           if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */ | 
 | 7843 |             dbug(1,dprintf("56k sync HSCX")); | 
 | 7844 |             cai[1] = 8; | 
 | 7845 |             cai[2] = 0; | 
 | 7846 |             cai[3] = 0; | 
 | 7847 |           } | 
 | 7848 |           else if(GET_WORD(bp_parms[0].info)==2){ | 
 | 7849 |             dbug(1,dprintf("56k async DSP")); | 
 | 7850 |             cai[2] = 9; | 
 | 7851 |           } | 
 | 7852 |           break; | 
 | 7853 |         case 50:     cai[2] = 1;  break; | 
 | 7854 |         case 75:     cai[2] = 1;  break; | 
 | 7855 |         case 110:    cai[2] = 1;  break; | 
 | 7856 |         case 150:    cai[2] = 1;  break; | 
 | 7857 |         case 200:    cai[2] = 1;  break; | 
 | 7858 |         case 300:    cai[2] = 1;  break; | 
 | 7859 |         case 600:    cai[2] = 1;  break; | 
 | 7860 |         case 1200:   cai[2] = 2;  break; | 
 | 7861 |         case 2400:   cai[2] = 3;  break; | 
 | 7862 |         case 4800:   cai[2] = 4;  break; | 
 | 7863 |         case 7200:   cai[2] = 10; break; | 
 | 7864 |         case 9600:   cai[2] = 5;  break; | 
 | 7865 |         case 12000:  cai[2] = 13; break; | 
 | 7866 |         case 24000:  cai[2] = 0;  break; | 
 | 7867 |         case 14400:  cai[2] = 11; break; | 
 | 7868 |         case 19200:  cai[2] = 6;  break; | 
 | 7869 |         case 28800:  cai[2] = 12; break; | 
 | 7870 |         case 38400:  cai[2] = 7;  break; | 
 | 7871 |         case 48000:  cai[2] = 8;  break; | 
 | 7872 |         case 76:     cai[2] = 15; break;  /* 75/1200     */ | 
 | 7873 |         case 1201:   cai[2] = 14; break;  /* 1200/75     */ | 
 | 7874 |         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */ | 
 | 7875 |  | 
 | 7876 |         default: | 
 | 7877 |           return _B1_PARM_NOT_SUPPORTED; | 
 | 7878 |       } | 
 | 7879 |       cai[3] = 0; | 
 | 7880 |       if (cai[1] == 13)                                        /* v.110 async */ | 
 | 7881 |       { | 
 | 7882 |         if (bp_parms[3].length >= 8) | 
 | 7883 |         { | 
 | 7884 |           switch (GET_WORD (&bp_parms[3].info[3])) | 
 | 7885 |           {       /* char length */ | 
 | 7886 |           case 5: | 
 | 7887 |             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5; | 
 | 7888 |             break; | 
 | 7889 |           case 6: | 
 | 7890 |             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6; | 
 | 7891 |             break; | 
 | 7892 |           case 7: | 
 | 7893 |             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7; | 
 | 7894 |             break; | 
 | 7895 |           } | 
 | 7896 |           switch (GET_WORD (&bp_parms[3].info[5])) | 
 | 7897 |           {       /* Parity     */ | 
 | 7898 |           case 1: /* odd parity */ | 
 | 7899 |             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD); | 
 | 7900 |             break; | 
 | 7901 |           case 2: /* even parity */ | 
 | 7902 |             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN); | 
 | 7903 |             break; | 
 | 7904 |           } | 
 | 7905 |           switch (GET_WORD (&bp_parms[3].info[7])) | 
 | 7906 |           {       /* stop bits   */ | 
 | 7907 |           case 1: /* 2 stop bits */ | 
 | 7908 |             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS; | 
 | 7909 |             break; | 
 | 7910 |           } | 
 | 7911 |         } | 
 | 7912 |       } | 
 | 7913 |     } | 
 | 7914 |     else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){ | 
 | 7915 |       dbug(1,dprintf("V.110 default 56k sync")); | 
 | 7916 |       cai[1] = 8; | 
 | 7917 |       cai[2] = 0; | 
 | 7918 |       cai[3] = 0; | 
 | 7919 |     } | 
 | 7920 |     else { | 
 | 7921 |       dbug(1,dprintf("V.110 default 9600 async")); | 
 | 7922 |       cai[2] = 5; | 
 | 7923 |     } | 
 | 7924 |   } | 
 | 7925 |   PUT_WORD(&cai[5],plci->appl->MaxDataLength); | 
 | 7926 |   dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6])); | 
 | 7927 | /* HexDump ("CAI", sizeof(cai), &cai[0]); */ | 
 | 7928 |  | 
 | 7929 |   add_p(plci, CAI, cai); | 
 | 7930 |   return 0; | 
 | 7931 | } | 
 | 7932 |  | 
 | 7933 | /*------------------------------------------------------------------*/ | 
 | 7934 | /* put parameter for b2 and B3  protocol in the parameter buffer    */ | 
 | 7935 | /*------------------------------------------------------------------*/ | 
 | 7936 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 7937 | static word add_b23(PLCI *plci, API_PARSE *bp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7938 | { | 
 | 7939 |   word i, fax_control_bits; | 
 | 7940 |   byte pos, len; | 
 | 7941 |   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */ | 
 | 7942 |     API_PARSE bp_parms[8]; | 
 | 7943 |   API_PARSE * b1_config; | 
 | 7944 |   API_PARSE * b2_config; | 
 | 7945 |     API_PARSE b2_config_parms[8]; | 
 | 7946 |   API_PARSE * b3_config; | 
 | 7947 |     API_PARSE b3_config_parms[6]; | 
 | 7948 |     API_PARSE global_config[2]; | 
 | 7949 |  | 
 | 7950 |   static byte llc[3] = {2,0,0}; | 
 | 7951 |   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | 
 | 7952 |   static byte nlc[256]; | 
 | 7953 |   static byte lli[12] = {1,1}; | 
 | 7954 |  | 
 | 7955 |   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6}; | 
 | 7956 |   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6}; | 
 | 7957 |  | 
 | 7958 |   const byte llc3[] = {4,3,2,2,6,6,0}; | 
 | 7959 |   const byte header[] = {0,2,3,3,0,0,0}; | 
 | 7960 |  | 
 | 7961 |   for(i=0;i<8;i++) bp_parms[i].length = 0; | 
 | 7962 |   for(i=0;i<6;i++) b2_config_parms[i].length = 0; | 
 | 7963 |   for(i=0;i<5;i++) b3_config_parms[i].length = 0; | 
 | 7964 |  | 
 | 7965 |   lli[0] = 1; | 
 | 7966 |   lli[1] = 1; | 
 | 7967 |   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) | 
 | 7968 |     lli[1] |= 2; | 
 | 7969 |   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) | 
 | 7970 |     lli[1] |= 4; | 
 | 7971 |  | 
 | 7972 |   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) { | 
 | 7973 |     lli[1] |= 0x10; | 
 | 7974 |     if (plci->rx_dma_descriptor <= 0) { | 
 | 7975 |       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic); | 
 | 7976 |       if (plci->rx_dma_descriptor >= 0) | 
 | 7977 |         plci->rx_dma_descriptor++; | 
 | 7978 |     } | 
 | 7979 |     if (plci->rx_dma_descriptor > 0) { | 
 | 7980 |       lli[0] = 6; | 
 | 7981 |       lli[1] |= 0x40; | 
 | 7982 |       lli[2] = (byte)(plci->rx_dma_descriptor - 1); | 
 | 7983 |       lli[3] = (byte)plci->rx_dma_magic; | 
 | 7984 |       lli[4] = (byte)(plci->rx_dma_magic >>  8); | 
 | 7985 |       lli[5] = (byte)(plci->rx_dma_magic >> 16); | 
 | 7986 |       lli[6] = (byte)(plci->rx_dma_magic >> 24); | 
 | 7987 |     } | 
 | 7988 |   } | 
 | 7989 |  | 
 | 7990 |   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) { | 
 | 7991 |     lli[1] |= 0x20; | 
 | 7992 |   } | 
 | 7993 |  | 
 | 7994 |   dbug(1,dprintf("add_b23")); | 
 | 7995 |   api_save_msg(bp, "s", &plci->B_protocol); | 
 | 7996 |  | 
 | 7997 |   if(!bp->length && plci->tel) | 
 | 7998 |   { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 7999 |     plci->adv_nl = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8000 |     dbug(1,dprintf("Default adv.Nl")); | 
 | 8001 |     add_p(plci,LLI,lli); | 
 | 8002 |     plci->B2_prot = 1 /*XPARENT*/; | 
 | 8003 |     plci->B3_prot = 0 /*XPARENT*/; | 
 | 8004 |     llc[1] = 2; | 
 | 8005 |     llc[2] = 4; | 
 | 8006 |     add_p(plci, LLC, llc); | 
 | 8007 |     dlc[0] = 2; | 
 | 8008 |     PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | 
 | 8009 |     add_p(plci, DLC, dlc); | 
 | 8010 |     return 0; | 
 | 8011 |   } | 
 | 8012 |  | 
 | 8013 |   if(!bp->length) /*default*/ | 
 | 8014 |   {    | 
 | 8015 |     dbug(1,dprintf("ret default")); | 
 | 8016 |     add_p(plci,LLI,lli); | 
 | 8017 |     plci->B2_prot = 0 /*X.75   */; | 
 | 8018 |     plci->B3_prot = 0 /*XPARENT*/; | 
 | 8019 |     llc[1] = 1; | 
 | 8020 |     llc[2] = 4; | 
 | 8021 |     add_p(plci, LLC, llc); | 
 | 8022 |     dlc[0] = 2; | 
 | 8023 |     PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | 
 | 8024 |     add_p(plci, DLC, dlc); | 
 | 8025 |     return 0; | 
 | 8026 |   } | 
 | 8027 |   dbug(1,dprintf("b_prot_len=%d",(word)bp->length)); | 
 | 8028 |   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT; | 
 | 8029 |  | 
 | 8030 |   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms)) | 
 | 8031 |   { | 
 | 8032 |     bp_parms[6].length = 0; | 
 | 8033 |     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms)) | 
 | 8034 |     { | 
 | 8035 |       dbug(1,dprintf("b-form.!")); | 
 | 8036 |       return _WRONG_MESSAGE_FORMAT; | 
 | 8037 |     } | 
 | 8038 |   } | 
 | 8039 |   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms)) | 
 | 8040 |   { | 
 | 8041 |     dbug(1,dprintf("b-form.!")); | 
 | 8042 |     return _WRONG_MESSAGE_FORMAT; | 
 | 8043 |   } | 
 | 8044 |  | 
 | 8045 |   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */ | 
 | 8046 |   {   | 
 | 8047 |     if(GET_WORD(bp_parms[1].info)!=1 | 
 | 8048 |     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 8049 |     plci->adv_nl = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8050 |   } | 
 | 8051 |   else if(plci->tel) return _B2_NOT_SUPPORTED; | 
 | 8052 |  | 
 | 8053 |  | 
 | 8054 |   if ((GET_WORD(bp_parms[1].info) == B2_RTP) | 
 | 8055 |    && (GET_WORD(bp_parms[2].info) == B3_RTP) | 
 | 8056 |    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP))) | 
 | 8057 |   { | 
 | 8058 |     add_p(plci,LLI,lli); | 
 | 8059 |     plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); | 
 | 8060 |     plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); | 
 | 8061 |     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13; | 
 | 8062 |     llc[2] = 4; | 
 | 8063 |     add_p(plci, LLC, llc); | 
 | 8064 |     dlc[0] = 2; | 
 | 8065 |     PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | 
 | 8066 |     dlc[3] = 3; /* Addr A */ | 
 | 8067 |     dlc[4] = 1; /* Addr B */ | 
 | 8068 |     dlc[5] = 7; /* modulo mode */ | 
 | 8069 |     dlc[6] = 7; /* window size */ | 
 | 8070 |     dlc[7] = 0; /* XID len Lo  */ | 
 | 8071 |     dlc[8] = 0; /* XID len Hi  */ | 
 | 8072 |     for (i = 0; i < bp_parms[4].length; i++) | 
 | 8073 |       dlc[9+i] = bp_parms[4].info[1+i]; | 
 | 8074 |     dlc[0] = (byte)(8 + bp_parms[4].length); | 
 | 8075 |     add_p(plci, DLC, dlc); | 
 | 8076 |     for (i = 0; i < bp_parms[5].length; i++) | 
 | 8077 |       nlc[1+i] = bp_parms[5].info[1+i]; | 
 | 8078 |     nlc[0] = (byte)(bp_parms[5].length); | 
 | 8079 |     add_p(plci, NLC, nlc); | 
 | 8080 |     return 0; | 
 | 8081 |   } | 
 | 8082 |  | 
 | 8083 |  | 
 | 8084 |  | 
 | 8085 |   if ((GET_WORD(bp_parms[1].info) >= 32) | 
 | 8086 |    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols) | 
 | 8087 |     && ((GET_WORD(bp_parms[1].info) != B2_PIAFS) | 
 | 8088 |      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS))))) | 
 | 8089 |  | 
 | 8090 |   { | 
 | 8091 |     return _B2_NOT_SUPPORTED; | 
 | 8092 |   } | 
 | 8093 |   if ((GET_WORD(bp_parms[2].info) >= 32) | 
 | 8094 |    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols)) | 
 | 8095 |   { | 
 | 8096 |     return _B3_NOT_SUPPORTED; | 
 | 8097 |   } | 
 | 8098 |   if ((GET_WORD(bp_parms[1].info) != B2_SDLC) | 
 | 8099 |    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) | 
 | 8100 |     || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC) | 
 | 8101 |     || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))) | 
 | 8102 |   { | 
 | 8103 |     return (add_modem_b23 (plci, bp_parms)); | 
 | 8104 |   } | 
 | 8105 |  | 
 | 8106 |   add_p(plci,LLI,lli); | 
 | 8107 |  | 
 | 8108 |   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); | 
 | 8109 |   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); | 
 | 8110 |   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */ | 
 | 8111 |  | 
 | 8112 |   if(bp_parms[6].length) | 
 | 8113 |   { | 
 | 8114 |     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config)) | 
 | 8115 |     { | 
 | 8116 |       return _WRONG_MESSAGE_FORMAT; | 
 | 8117 |     } | 
 | 8118 |     switch(GET_WORD(global_config[0].info)) | 
 | 8119 |     { | 
 | 8120 |     case 1: | 
 | 8121 |       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE; | 
 | 8122 |       break; | 
 | 8123 |     case 2: | 
 | 8124 |       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER; | 
 | 8125 |       break; | 
 | 8126 |     } | 
 | 8127 |   } | 
 | 8128 |   dbug(1,dprintf("call_dir=%04x", plci->call_dir)); | 
 | 8129 |  | 
 | 8130 |  | 
 | 8131 |   if (plci->B2_prot == B2_PIAFS) | 
 | 8132 |     llc[1] = PIAFS_CRC; | 
 | 8133 |   else | 
 | 8134 | /* IMPLEMENT_PIAFS */ | 
 | 8135 |   { | 
 | 8136 |     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? | 
 | 8137 |              llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)]; | 
 | 8138 |   } | 
 | 8139 |   llc[2] = llc3[GET_WORD(bp_parms[2].info)]; | 
 | 8140 |  | 
 | 8141 |   add_p(plci, LLC, llc); | 
 | 8142 |  | 
 | 8143 |   dlc[0] = 2; | 
 | 8144 |   PUT_WORD(&dlc[1], plci->appl->MaxDataLength + | 
 | 8145 |                       header[GET_WORD(bp_parms[2].info)]); | 
 | 8146 |  | 
 | 8147 |   b1_config = &bp_parms[3]; | 
 | 8148 |   nlc[0] = 0; | 
 | 8149 |   if(plci->B3_prot == 4 | 
 | 8150 |   || plci->B3_prot == 5) | 
 | 8151 |   { | 
 | 8152 |     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0; | 
 | 8153 |     nlc[0] = sizeof(T30_INFO); | 
 | 8154 |     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | 
 | 8155 |       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI; | 
 | 8156 |     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff; | 
 | 8157 |     if(b1_config->length>=2) | 
 | 8158 |     { | 
 | 8159 |       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400); | 
 | 8160 |     } | 
 | 8161 |   } | 
 | 8162 |   b2_config = &bp_parms[4]; | 
 | 8163 |  | 
 | 8164 |  | 
 | 8165 |   if (llc[1] == PIAFS_CRC) | 
 | 8166 |   { | 
 | 8167 |     if (plci->B3_prot != B3_TRANSPARENT) | 
 | 8168 |     { | 
 | 8169 |       return _B_STACK_NOT_SUPPORTED; | 
 | 8170 |     } | 
 | 8171 |     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) { | 
 | 8172 |       return _WRONG_MESSAGE_FORMAT; | 
 | 8173 |     } | 
 | 8174 |     PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | 
 | 8175 |     dlc[3] = 0; /* Addr A */ | 
 | 8176 |     dlc[4] = 0; /* Addr B */ | 
 | 8177 |     dlc[5] = 0; /* modulo mode */ | 
 | 8178 |     dlc[6] = 0; /* window size */ | 
 | 8179 |     if (b2_config->length >= 7){ | 
 | 8180 |       dlc[ 7] = 7;  | 
 | 8181 |       dlc[ 8] = 0;  | 
 | 8182 |       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */ | 
 | 8183 |       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */ | 
 | 8184 |       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */ | 
 | 8185 |       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */ | 
 | 8186 |       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */ | 
 | 8187 |       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */ | 
 | 8188 |       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */ | 
 | 8189 |       dlc[ 0] = 15; | 
 | 8190 |       if(b2_config->length >= 8) { /* PIAFS control abilities */ | 
 | 8191 |         dlc[ 7] = 10;  | 
 | 8192 |         dlc[16] = 2; /* Length of PIAFS extention */ | 
 | 8193 |         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */ | 
 | 8194 |         dlc[18] = b2_config_parms[4].info[0]; /* value */ | 
 | 8195 |         dlc[ 0] = 18; | 
 | 8196 |       } | 
 | 8197 |     } | 
 | 8198 |     else /* default values, 64K, variable, no compression */ | 
 | 8199 |     { | 
 | 8200 |       dlc[ 7] = 7;  | 
 | 8201 |       dlc[ 8] = 0;  | 
 | 8202 |       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */ | 
 | 8203 |       dlc[10] = 0x03; /* V.42bis P0 */ | 
 | 8204 |       dlc[11] = 0;    /* V.42bis P0 */ | 
 | 8205 |       dlc[12] = 0;    /* V.42bis P1 */ | 
 | 8206 |       dlc[13] = 0;    /* V.42bis P1 */ | 
 | 8207 |       dlc[14] = 0;    /* V.42bis P2 */ | 
 | 8208 |       dlc[15] = 0;    /* V.42bis P2 */ | 
 | 8209 |     dlc[ 0] = 15; | 
 | 8210 |     } | 
 | 8211 |     add_p(plci, DLC, dlc); | 
 | 8212 |   } | 
 | 8213 |   else | 
 | 8214 |  | 
 | 8215 |   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS)) | 
 | 8216 |   { | 
 | 8217 |     if (plci->B3_prot != B3_TRANSPARENT) | 
 | 8218 |       return _B_STACK_NOT_SUPPORTED; | 
 | 8219 |  | 
 | 8220 |     dlc[0] = 6; | 
 | 8221 |     PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2); | 
 | 8222 |     dlc[3] = 0x08; | 
 | 8223 |     dlc[4] = 0x01; | 
 | 8224 |     dlc[5] = 127; | 
 | 8225 |     dlc[6] = 7; | 
 | 8226 |     if (b2_config->length != 0) | 
 | 8227 |     { | 
 | 8228 |       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) { | 
 | 8229 |         return _WRONG_MESSAGE_FORMAT; | 
 | 8230 |       } | 
 | 8231 |       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04)); | 
 | 8232 |       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01); | 
 | 8233 |       if (b2_config->info[3] != 128) | 
 | 8234 |       { | 
 | 8235 |         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4])); | 
 | 8236 |         return _B2_PARM_NOT_SUPPORTED; | 
 | 8237 |       } | 
 | 8238 |       dlc[5] = (byte)(b2_config->info[3] - 1); | 
 | 8239 |       dlc[6] = b2_config->info[4]; | 
 | 8240 |       if(llc[1]==V120_V42BIS){ | 
 | 8241 |         if (b2_config->length >= 10){ | 
 | 8242 |           dlc[ 7] = 6;  | 
 | 8243 |           dlc[ 8] = 0;  | 
 | 8244 |           dlc[ 9] = b2_config_parms[4].info[0]; | 
 | 8245 |           dlc[10] = b2_config_parms[4].info[1]; | 
 | 8246 |           dlc[11] = b2_config_parms[5].info[0]; | 
 | 8247 |           dlc[12] = b2_config_parms[5].info[1]; | 
 | 8248 |           dlc[13] = b2_config_parms[6].info[0]; | 
 | 8249 |           dlc[14] = b2_config_parms[6].info[1]; | 
 | 8250 |           dlc[ 0] = 14; | 
 | 8251 |           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1])); | 
 | 8252 |           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1])); | 
 | 8253 |           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1])); | 
 | 8254 |         } | 
 | 8255 |         else { | 
 | 8256 |           dlc[ 6] = 14; | 
 | 8257 |         } | 
 | 8258 |       } | 
 | 8259 |     } | 
 | 8260 |   } | 
 | 8261 |   else | 
 | 8262 |   { | 
 | 8263 |     if(b2_config->length) | 
 | 8264 |     { | 
 | 8265 |       dbug(1,dprintf("B2-Config")); | 
 | 8266 |       if(llc[1]==X75_V42BIS){ | 
 | 8267 |         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) | 
 | 8268 |         { | 
 | 8269 |           return _WRONG_MESSAGE_FORMAT; | 
 | 8270 |         } | 
 | 8271 |       } | 
 | 8272 |       else { | 
 | 8273 |         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms)) | 
 | 8274 |         { | 
 | 8275 |           return _WRONG_MESSAGE_FORMAT; | 
 | 8276 |         } | 
 | 8277 |       } | 
 | 8278 |           /* if B2 Protocol is LAPD, b2_config structure is different */ | 
 | 8279 |       if(llc[1]==6) | 
 | 8280 |       { | 
 | 8281 |         dlc[0] = 4; | 
 | 8282 |         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */ | 
 | 8283 |         else dlc[2] = 0x01; | 
 | 8284 |         if( (b2_config->length>=2) && (plci->B2_prot==12) ) | 
 | 8285 |         { | 
 | 8286 |           SAPI = b2_config->info[2];    /* SAPI */ | 
 | 8287 |         } | 
 | 8288 |         dlc[1] = SAPI; | 
 | 8289 |         if( (b2_config->length>=3) && (b2_config->info[3]==128) ) | 
 | 8290 |         { | 
 | 8291 |           dlc[3] = 127;      /* Mode */ | 
 | 8292 |         } | 
 | 8293 |         else | 
 | 8294 |         { | 
 | 8295 |           dlc[3] = 7;        /* Mode */ | 
 | 8296 |         } | 
 | 8297 |     | 
 | 8298 |         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */ | 
 | 8299 |         else dlc[4] = 1; | 
 | 8300 |         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4])); | 
 | 8301 |         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED; | 
 | 8302 |       } | 
 | 8303 |       else | 
 | 8304 |       { | 
 | 8305 |         dlc[0] = (byte)(b2_config_parms[4].length+6); | 
 | 8306 |         dlc[3] = b2_config->info[1]; | 
 | 8307 |         dlc[4] = b2_config->info[2]; | 
 | 8308 |         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){ | 
 | 8309 |           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4])); | 
 | 8310 |           return _B2_PARM_NOT_SUPPORTED; | 
 | 8311 |         } | 
 | 8312 |  | 
 | 8313 |         dlc[5] = (byte)(b2_config->info[3]-1); | 
 | 8314 |         dlc[6] = b2_config->info[4]; | 
 | 8315 |         if(dlc[6]>dlc[5]){ | 
 | 8316 |           dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6])); | 
 | 8317 |           return _B2_PARM_NOT_SUPPORTED; | 
 | 8318 |         } | 
 | 8319 |   | 
 | 8320 |         if(llc[1]==X75_V42BIS) { | 
 | 8321 |           if (b2_config->length >= 10){ | 
 | 8322 |             dlc[ 7] = 6;  | 
 | 8323 |             dlc[ 8] = 0;  | 
 | 8324 |             dlc[ 9] = b2_config_parms[4].info[0]; | 
 | 8325 |             dlc[10] = b2_config_parms[4].info[1]; | 
 | 8326 |             dlc[11] = b2_config_parms[5].info[0]; | 
 | 8327 |             dlc[12] = b2_config_parms[5].info[1]; | 
 | 8328 |             dlc[13] = b2_config_parms[6].info[0]; | 
 | 8329 |             dlc[14] = b2_config_parms[6].info[1]; | 
 | 8330 |             dlc[ 0] = 14; | 
 | 8331 |             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1])); | 
 | 8332 |             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1])); | 
 | 8333 |             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1])); | 
 | 8334 |           } | 
 | 8335 |           else { | 
 | 8336 |             dlc[ 6] = 14; | 
 | 8337 |           } | 
 | 8338 |  | 
 | 8339 |         } | 
 | 8340 |         else { | 
 | 8341 |           PUT_WORD(&dlc[7], (word)b2_config_parms[4].length); | 
 | 8342 |           for(i=0; i<b2_config_parms[4].length; i++) | 
 | 8343 |             dlc[11+i] = b2_config_parms[4].info[1+i]; | 
 | 8344 |         } | 
 | 8345 |       } | 
 | 8346 |     } | 
 | 8347 |   } | 
 | 8348 |   add_p(plci, DLC, dlc); | 
 | 8349 |  | 
 | 8350 |   b3_config = &bp_parms[5]; | 
 | 8351 |   if(b3_config->length) | 
 | 8352 |   { | 
 | 8353 |     if(plci->B3_prot == 4  | 
 | 8354 |     || plci->B3_prot == 5) | 
 | 8355 |     { | 
 | 8356 |       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms)) | 
 | 8357 |       { | 
 | 8358 |         return _WRONG_MESSAGE_FORMAT; | 
 | 8359 |       } | 
 | 8360 |       i = GET_WORD((byte   *)(b3_config_parms[0].info)); | 
 | 8361 |       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) || | 
 | 8362 |         ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0); | 
 | 8363 |       ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info)); | 
 | 8364 |       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES; | 
 | 8365 |       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6)) | 
 | 8366 |         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX; | 
 | 8367 |       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | 
 | 8368 |       { | 
 | 8369 |  | 
 | 8370 |         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | 
 | 8371 |           & (1L << PRIVATE_FAX_PAPER_FORMATS)) | 
 | 8372 |         { | 
 | 8373 |           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 | | 
 | 8374 |             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 | | 
 | 8375 |             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED; | 
 | 8376 |         } | 
 | 8377 |  | 
 | 8378 |  ((T30_INFO *)&nlc[1])->recording_properties = | 
 | 8379 |    T30_RECORDING_WIDTH_ISO_A3 | | 
 | 8380 |    (T30_RECORDING_LENGTH_UNLIMITED << 2) | | 
 | 8381 |    (T30_MIN_SCANLINE_TIME_00_00_00 << 4); | 
 | 8382 |       } | 
 | 8383 |       if(plci->B3_prot == 5) | 
 | 8384 |       { | 
 | 8385 |         if (i & 0x0002) /* Accept incoming fax-polling requests */ | 
 | 8386 |           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING; | 
 | 8387 |         if (i & 0x2000) /* Do not use MR compression */ | 
 | 8388 |           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING; | 
 | 8389 |         if (i & 0x4000) /* Do not use MMR compression */ | 
 | 8390 |           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING; | 
 | 8391 |         if (i & 0x8000) /* Do not use ECM */ | 
 | 8392 |           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM; | 
 | 8393 |         if (plci->fax_connect_info_length != 0) | 
 | 8394 |         { | 
 | 8395 |           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution; | 
 | 8396 |           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format; | 
 | 8397 |           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties; | 
 | 8398 |           fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & | 
 | 8399 |             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS); | 
 | 8400 |         } | 
 | 8401 |       } | 
 | 8402 |       /* copy station id to NLC */ | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8403 |       for(i=0; i < T30_MAX_STATION_ID_LENGTH; i++) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8404 |       { | 
 | 8405 |         if(i<b3_config_parms[2].length) | 
 | 8406 |         { | 
 | 8407 |           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i]; | 
 | 8408 |         } | 
 | 8409 |         else | 
 | 8410 |         { | 
 | 8411 |           ((T30_INFO *)&nlc[1])->station_id[i] = ' '; | 
 | 8412 |         } | 
 | 8413 |       } | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8414 |       ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8415 |       /* copy head line to NLC */ | 
 | 8416 |       if(b3_config_parms[3].length) | 
 | 8417 |       { | 
 | 8418 |  | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8419 |         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH]))); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8420 |         if (pos != 0) | 
 | 8421 |         { | 
 | 8422 |           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE) | 
 | 8423 |             pos = 0; | 
 | 8424 |           else | 
 | 8425 |           { | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8426 |             nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; | 
 | 8427 |             nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8428 |             len = (byte)b3_config_parms[2].length; | 
 | 8429 |             if (len > 20) | 
 | 8430 |               len = 20; | 
 | 8431 |             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE) | 
 | 8432 |             { | 
 | 8433 |               for (i = 0; i < len; i++) | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8434 |                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte   *)b3_config_parms[2].info)[1+i]; | 
 | 8435 |               nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; | 
 | 8436 |               nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8437 |             } | 
 | 8438 |           } | 
 | 8439 |         } | 
 | 8440 |  | 
 | 8441 |         len = (byte)b3_config_parms[3].length; | 
 | 8442 |         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos) | 
 | 8443 |           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos); | 
 | 8444 |         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len); | 
 | 8445 |         nlc[0] += (byte)(pos + len); | 
 | 8446 |         for (i = 0; i < len; i++) | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8447 |           nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte   *)b3_config_parms[3].info)[1+i]; | 
| Ian Munsie | 8b4017d | 2010-03-11 12:07:24 +0000 | [diff] [blame] | 8448 |       } else | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8449 |         ((T30_INFO *)&nlc[1])->head_line_len = 0; | 
 | 8450 |  | 
 | 8451 |       plci->nsf_control_bits = 0; | 
 | 8452 |       if(plci->B3_prot == 5) | 
 | 8453 |       { | 
 | 8454 |         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | 
 | 8455 |          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */ | 
 | 8456 |         { | 
 | 8457 |           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD; | 
 | 8458 |         } | 
 | 8459 |         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD)) | 
 | 8460 |          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */ | 
 | 8461 |         { | 
 | 8462 |           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD; | 
 | 8463 |         } | 
 | 8464 |         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | 
 | 8465 |           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | 
 | 8466 |         { | 
 | 8467 |         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | 
 | 8468 |           & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | 
 | 8469 |         { | 
 | 8470 |           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD; | 
 | 8471 |           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING) | 
 | 8472 |             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; | 
 | 8473 |           } | 
 | 8474 |             len = nlc[0]; | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8475 |           pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8476 |    if (pos < plci->fax_connect_info_length) | 
 | 8477 |    { | 
 | 8478 |      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) | 
 | 8479 |               nlc[++len] = plci->fax_connect_info_buffer[pos++]; | 
 | 8480 |           } | 
 | 8481 |    else | 
 | 8482 |      nlc[++len] = 0; | 
 | 8483 |    if (pos < plci->fax_connect_info_length) | 
 | 8484 |    { | 
 | 8485 |      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) | 
 | 8486 |               nlc[++len] = plci->fax_connect_info_buffer[pos++]; | 
 | 8487 |           } | 
 | 8488 |    else | 
 | 8489 |      nlc[++len] = 0; | 
 | 8490 |           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | 
 | 8491 |             & (1L << PRIVATE_FAX_NONSTANDARD)) | 
 | 8492 |           { | 
 | 8493 |      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0)) | 
 | 8494 |      { | 
 | 8495 |               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2)) | 
 | 8496 |                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]); | 
 | 8497 |        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) | 
 | 8498 |                 nlc[++len] = plci->fax_connect_info_buffer[pos++]; | 
 | 8499 |             } | 
 | 8500 |      else | 
 | 8501 |      { | 
 | 8502 |               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms)) | 
 | 8503 |               { | 
 | 8504 |                 dbug(1,dprintf("non-standard facilities info missing or wrong format")); | 
 | 8505 |                 nlc[++len] = 0; | 
 | 8506 |               } | 
 | 8507 |        else | 
 | 8508 |        { | 
 | 8509 |                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2)) | 
 | 8510 |                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]); | 
 | 8511 |          nlc[++len] = (byte)(b3_config_parms[4].length); | 
 | 8512 |          for (i = 0; i < b3_config_parms[4].length; i++) | 
 | 8513 |     nlc[++len] = b3_config_parms[4].info[1+i]; | 
 | 8514 |        } | 
 | 8515 |             } | 
 | 8516 |           } | 
 | 8517 |             nlc[0] = len; | 
 | 8518 |    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) | 
 | 8519 |     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) | 
 | 8520 |    { | 
 | 8521 |             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG; | 
 | 8522 |           } | 
 | 8523 |         } | 
 | 8524 |       } | 
 | 8525 |  | 
 | 8526 |       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); | 
| Ian Munsie | 255f5c3 | 2010-03-11 12:07:25 +0000 | [diff] [blame] | 8527 |       len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8528 |       for (i = 0; i < len; i++) | 
 | 8529 |         plci->fax_connect_info_buffer[i] = nlc[1+i]; | 
 | 8530 |       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0; | 
 | 8531 |       i += ((T30_INFO *)&nlc[1])->head_line_len; | 
 | 8532 |       while (i < nlc[0]) | 
 | 8533 |         plci->fax_connect_info_buffer[len++] = nlc[++i]; | 
 | 8534 |       plci->fax_connect_info_length = len; | 
 | 8535 |     } | 
 | 8536 |     else | 
 | 8537 |     { | 
 | 8538 |       nlc[0] = 14; | 
 | 8539 |       if(b3_config->length!=16) | 
 | 8540 |         return _B3_PARM_NOT_SUPPORTED; | 
 | 8541 |       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i]; | 
 | 8542 |       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128) | 
 | 8543 |         return _B3_PARM_NOT_SUPPORTED; | 
 | 8544 |       nlc[13] = b3_config->info[13]; | 
 | 8545 |       if(GET_WORD(&b3_config->info[15])>=nlc[13]) | 
 | 8546 |         return _B3_PARM_NOT_SUPPORTED; | 
 | 8547 |       nlc[14] = b3_config->info[15]; | 
 | 8548 |     } | 
 | 8549 |   } | 
 | 8550 |   else | 
 | 8551 |   { | 
 | 8552 |     if (plci->B3_prot == 4  | 
 | 8553 |      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED; | 
 | 8554 |   } | 
 | 8555 |   add_p(plci, NLC, nlc); | 
 | 8556 |   return 0; | 
 | 8557 | } | 
 | 8558 |  | 
 | 8559 | /*----------------------------------------------------------------*/ | 
 | 8560 | /*      make the same as add_b23, but only for the modem related  */ | 
 | 8561 | /*      L2 and L3 B-Chan protocol.                                */ | 
 | 8562 | /*                                                                */ | 
 | 8563 | /*      Enabled L2 and L3 Configurations:                         */ | 
 | 8564 | /*        If L1 == Modem all negotiation                          */ | 
 | 8565 | /*          only L2 == Modem with full negotiation is allowed     */ | 
 | 8566 | /*        If L1 == Modem async or sync                            */ | 
 | 8567 | /*          only L2 == Transparent is allowed                     */ | 
 | 8568 | /*        L3 == Modem or L3 == Transparent are allowed            */ | 
 | 8569 | /*      B2 Configuration for modem:                               */ | 
 | 8570 | /*          word : enable/disable compression, bitoptions         */ | 
 | 8571 | /*      B3 Configuration for modem:                               */ | 
 | 8572 | /*          empty                                                 */ | 
 | 8573 | /*----------------------------------------------------------------*/ | 
 | 8574 | static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms) | 
 | 8575 | { | 
 | 8576 |   static byte lli[12] = {1,1}; | 
 | 8577 |   static byte llc[3] = {2,0,0}; | 
 | 8578 |   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | 
 | 8579 |     API_PARSE mdm_config[2]; | 
 | 8580 |   word i; | 
 | 8581 |   word b2_config = 0; | 
 | 8582 |  | 
 | 8583 |   for(i=0;i<2;i++) mdm_config[i].length = 0; | 
 | 8584 |   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0; | 
 | 8585 |  | 
 | 8586 |   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) | 
 | 8587 |     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION)) | 
 | 8588 |    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE) | 
 | 8589 |     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT))) | 
 | 8590 |   { | 
 | 8591 |     return (_B_STACK_NOT_SUPPORTED); | 
 | 8592 |   } | 
 | 8593 |   if ((GET_WORD(bp_parms[2].info) != B3_MODEM) | 
 | 8594 |    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT)) | 
 | 8595 |   { | 
 | 8596 |     return (_B_STACK_NOT_SUPPORTED); | 
 | 8597 |   } | 
 | 8598 |  | 
 | 8599 |   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); | 
 | 8600 |   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); | 
 | 8601 |  | 
 | 8602 |   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length) | 
 | 8603 |   { | 
 | 8604 |     if (api_parse (&bp_parms[4].info[1], | 
 | 8605 |                   (word)bp_parms[4].length, "w", | 
 | 8606 |                   mdm_config)) | 
 | 8607 |     { | 
 | 8608 |       return (_WRONG_MESSAGE_FORMAT); | 
 | 8609 |     } | 
 | 8610 |     b2_config = GET_WORD(mdm_config[0].info); | 
 | 8611 |   } | 
 | 8612 |  | 
 | 8613 |   /* OK, L2 is modem */ | 
 | 8614 |  | 
 | 8615 |   lli[0] = 1; | 
 | 8616 |   lli[1] = 1; | 
 | 8617 |   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) | 
 | 8618 |     lli[1] |= 2; | 
 | 8619 |   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) | 
 | 8620 |     lli[1] |= 4; | 
 | 8621 |  | 
 | 8622 |   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) { | 
 | 8623 |     lli[1] |= 0x10; | 
 | 8624 |     if (plci->rx_dma_descriptor <= 0) { | 
 | 8625 |       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic); | 
 | 8626 |       if (plci->rx_dma_descriptor >= 0) | 
 | 8627 |         plci->rx_dma_descriptor++; | 
 | 8628 |     } | 
 | 8629 |     if (plci->rx_dma_descriptor > 0) { | 
 | 8630 |       lli[1] |= 0x40; | 
 | 8631 |       lli[0] = 6; | 
 | 8632 |       lli[2] = (byte)(plci->rx_dma_descriptor - 1); | 
 | 8633 |       lli[3] = (byte)plci->rx_dma_magic; | 
 | 8634 |       lli[4] = (byte)(plci->rx_dma_magic >>  8); | 
 | 8635 |       lli[5] = (byte)(plci->rx_dma_magic >> 16); | 
 | 8636 |       lli[6] = (byte)(plci->rx_dma_magic >> 24); | 
 | 8637 |     } | 
 | 8638 |   } | 
 | 8639 |  | 
 | 8640 |   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) { | 
 | 8641 |     lli[1] |= 0x20; | 
 | 8642 |   } | 
 | 8643 |  | 
 | 8644 |   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? | 
 | 8645 |     /*V42*/ 10 : /*V42_IN*/ 9; | 
 | 8646 |   llc[2] = 4;                      /* pass L3 always transparent */ | 
 | 8647 |   add_p(plci, LLI, lli); | 
 | 8648 |   add_p(plci, LLC, llc); | 
 | 8649 |   i =  1; | 
 | 8650 |   PUT_WORD (&dlc[i], plci->appl->MaxDataLength); | 
 | 8651 |   i += 2; | 
 | 8652 |   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) | 
 | 8653 |   { | 
 | 8654 |     if (bp_parms[4].length) | 
 | 8655 |   { | 
 | 8656 |     dbug(1, dprintf("MDM b2_config=%02x", b2_config)); | 
 | 8657 |     dlc[i++] = 3; /* Addr A */ | 
 | 8658 |     dlc[i++] = 1; /* Addr B */ | 
 | 8659 |     dlc[i++] = 7; /* modulo mode */ | 
 | 8660 |     dlc[i++] = 7; /* window size */ | 
 | 8661 |     dlc[i++] = 0; /* XID len Lo  */ | 
 | 8662 |     dlc[i++] = 0; /* XID len Hi  */ | 
 | 8663 |  | 
 | 8664 |     if (b2_config & MDM_B2_DISABLE_V42bis) | 
 | 8665 |     { | 
 | 8666 |       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS; | 
 | 8667 |     } | 
 | 8668 |     if (b2_config & MDM_B2_DISABLE_MNP) | 
 | 8669 |     { | 
 | 8670 |       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5; | 
 | 8671 |     } | 
 | 8672 |     if (b2_config & MDM_B2_DISABLE_TRANS) | 
 | 8673 |     { | 
 | 8674 |       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL; | 
 | 8675 |     } | 
 | 8676 |     if (b2_config & MDM_B2_DISABLE_V42) | 
 | 8677 |     { | 
 | 8678 |       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT; | 
 | 8679 |     } | 
 | 8680 |     if (b2_config & MDM_B2_DISABLE_COMP) | 
 | 8681 |     { | 
 | 8682 |       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION; | 
 | 8683 |     } | 
 | 8684 |     i++; | 
 | 8685 |   } | 
 | 8686 |   } | 
 | 8687 |   else | 
 | 8688 |   { | 
 | 8689 |     dlc[i++] = 3; /* Addr A */ | 
 | 8690 |     dlc[i++] = 1; /* Addr B */ | 
 | 8691 |     dlc[i++] = 7; /* modulo mode */ | 
 | 8692 |     dlc[i++] = 7; /* window size */ | 
 | 8693 |     dlc[i++] = 0; /* XID len Lo  */ | 
 | 8694 |     dlc[i++] = 0; /* XID len Hi  */ | 
 | 8695 |     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS | | 
 | 8696 |                DLC_MODEMPROT_DISABLE_MNP_MNP5 | | 
 | 8697 |                DLC_MODEMPROT_DISABLE_V42_DETECT | | 
 | 8698 |                DLC_MODEMPROT_DISABLE_COMPRESSION; | 
 | 8699 |   } | 
 | 8700 |   dlc[0] = (byte)(i - 1); | 
 | 8701 | /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */ | 
 | 8702 |   add_p(plci, DLC, dlc); | 
 | 8703 |   return (0); | 
 | 8704 | } | 
 | 8705 |  | 
 | 8706 |  | 
 | 8707 | /*------------------------------------------------------------------*/ | 
 | 8708 | /* send a request for the signaling entity                          */ | 
 | 8709 | /*------------------------------------------------------------------*/ | 
 | 8710 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 8711 | static void sig_req(PLCI *plci, byte req, byte Id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8712 | { | 
 | 8713 |   if(!plci) return; | 
 | 8714 |   if(plci->adapter->adapter_disabled) return; | 
 | 8715 |   dbug(1,dprintf("sig_req(%x)",req)); | 
 | 8716 |   if (req == REMOVE) | 
 | 8717 |     plci->sig_remove_id = plci->Sig.Id; | 
 | 8718 |   if(plci->req_in==plci->req_in_start) { | 
 | 8719 |     plci->req_in +=2; | 
 | 8720 |     plci->RBuffer[plci->req_in++] = 0; | 
 | 8721 |   } | 
 | 8722 |   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); | 
 | 8723 |   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */ | 
 | 8724 |   plci->RBuffer[plci->req_in++] = req;  /* request */ | 
 | 8725 |   plci->RBuffer[plci->req_in++] = 0;    /* channel */ | 
 | 8726 |   plci->req_in_start = plci->req_in; | 
 | 8727 | } | 
 | 8728 |  | 
 | 8729 | /*------------------------------------------------------------------*/ | 
 | 8730 | /* send a request for the network layer entity                      */ | 
 | 8731 | /*------------------------------------------------------------------*/ | 
 | 8732 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 8733 | static void nl_req_ncci(PLCI *plci, byte req, byte ncci) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8734 | { | 
 | 8735 |   if(!plci) return; | 
 | 8736 |   if(plci->adapter->adapter_disabled) return; | 
 | 8737 |   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci)); | 
 | 8738 |   if (req == REMOVE) | 
 | 8739 |   { | 
 | 8740 |     plci->nl_remove_id = plci->NL.Id; | 
 | 8741 |     ncci_remove (plci, 0, (byte)(ncci != 0)); | 
 | 8742 |     ncci = 0; | 
 | 8743 |   } | 
 | 8744 |   if(plci->req_in==plci->req_in_start) { | 
 | 8745 |     plci->req_in +=2; | 
 | 8746 |     plci->RBuffer[plci->req_in++] = 0; | 
 | 8747 |   } | 
 | 8748 |   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); | 
 | 8749 |   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */ | 
 | 8750 |   plci->RBuffer[plci->req_in++] = req;  /* request */ | 
 | 8751 |   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */ | 
 | 8752 |   plci->req_in_start = plci->req_in; | 
 | 8753 | } | 
 | 8754 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 8755 | static void send_req(PLCI *plci) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8756 | { | 
 | 8757 |   ENTITY   * e; | 
 | 8758 |   word l; | 
 | 8759 | /*  word i; */ | 
 | 8760 |  | 
 | 8761 |   if(!plci) return; | 
 | 8762 |   if(plci->adapter->adapter_disabled) return; | 
 | 8763 |   channel_xmit_xon (plci); | 
 | 8764 |  | 
 | 8765 |         /* if nothing to do, return */ | 
 | 8766 |   if(plci->req_in==plci->req_out) return; | 
 | 8767 |   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out)); | 
 | 8768 |  | 
 | 8769 |   if(plci->nl_req || plci->sig_req) return; | 
 | 8770 |  | 
 | 8771 |   l = GET_WORD(&plci->RBuffer[plci->req_out]); | 
 | 8772 |   plci->req_out += 2; | 
 | 8773 |   plci->XData[0].P = &plci->RBuffer[plci->req_out]; | 
 | 8774 |   plci->req_out += l; | 
 | 8775 |   if(plci->RBuffer[plci->req_out]==1) | 
 | 8776 |   { | 
 | 8777 |     e = &plci->NL; | 
 | 8778 |     plci->req_out++; | 
 | 8779 |     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++]; | 
 | 8780 |     e->ReqCh = plci->RBuffer[plci->req_out++]; | 
 | 8781 |     if(!(e->Id & 0x1f)) | 
 | 8782 |     { | 
 | 8783 |       e->Id = NL_ID; | 
 | 8784 |       plci->RBuffer[plci->req_out-4] = CAI; | 
 | 8785 |       plci->RBuffer[plci->req_out-3] = 1; | 
 | 8786 |       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id; | 
 | 8787 |       plci->RBuffer[plci->req_out-1] = 0; | 
 | 8788 |       l+=3; | 
 | 8789 |       plci->nl_global_req = plci->nl_req; | 
 | 8790 |     } | 
 | 8791 |     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh)); | 
 | 8792 |   } | 
 | 8793 |   else | 
 | 8794 |   { | 
 | 8795 |     e = &plci->Sig; | 
 | 8796 |     if(plci->RBuffer[plci->req_out]) | 
 | 8797 |       e->Id = plci->RBuffer[plci->req_out]; | 
 | 8798 |     plci->req_out++; | 
 | 8799 |     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++]; | 
 | 8800 |     e->ReqCh = plci->RBuffer[plci->req_out++]; | 
 | 8801 |     if(!(e->Id & 0x1f)) | 
 | 8802 |       plci->sig_global_req = plci->sig_req; | 
 | 8803 |     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh)); | 
 | 8804 |   } | 
 | 8805 |   plci->XData[0].PLength = l; | 
 | 8806 |   e->X = plci->XData; | 
 | 8807 |   plci->adapter->request(e); | 
 | 8808 |   dbug(1,dprintf("send_ok")); | 
 | 8809 | } | 
 | 8810 |  | 
| Hannes Eder | 465e985 | 2009-02-25 13:11:37 +0000 | [diff] [blame] | 8811 | static void send_data(PLCI *plci) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8812 | { | 
 | 8813 |   DIVA_CAPI_ADAPTER   * a; | 
 | 8814 |   DATA_B3_DESC   * data; | 
 | 8815 |   NCCI   *ncci_ptr; | 
 | 8816 |   word ncci; | 
 | 8817 |  | 
 | 8818 |   if (!plci->nl_req && plci->ncci_ring_list) | 
 | 8819 |   { | 
 | 8820 |     a = plci->adapter; | 
 | 8821 |     ncci = plci->ncci_ring_list; | 
 | 8822 |     do | 
 | 8823 |     { | 
 | 8824 |       ncci = a->ncci_next[ncci]; | 
 | 8825 |       ncci_ptr = &(a->ncci[ncci]); | 
 | 8826 |       if (!(a->ncci_ch[ncci] | 
 | 8827 |          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING))) | 
 | 8828 |       { | 
 | 8829 |         if (ncci_ptr->data_pending) | 
 | 8830 |         { | 
 | 8831 |           if ((a->ncci_state[ncci] == CONNECTED) | 
 | 8832 |            || (a->ncci_state[ncci] == INC_ACT_PENDING) | 
 | 8833 |            || (plci->send_disc == ncci)) | 
 | 8834 |           { | 
 | 8835 |             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]); | 
 | 8836 |             if ((plci->B2_prot == B2_V120_ASYNC) | 
 | 8837 |              || (plci->B2_prot == B2_V120_ASYNC_V42BIS) | 
 | 8838 |              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)) | 
 | 8839 |             { | 
 | 8840 |               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P); | 
 | 8841 |               plci->NData[1].PLength = data->Length; | 
 | 8842 |               if (data->Flags & 0x10) | 
 | 8843 |                 plci->NData[0].P = v120_break_header; | 
 | 8844 |               else | 
 | 8845 |                 plci->NData[0].P = v120_default_header; | 
 | 8846 |               plci->NData[0].PLength = 1 ; | 
 | 8847 |               plci->NL.XNum = 2; | 
 | 8848 |               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA); | 
 | 8849 |             } | 
 | 8850 |             else | 
 | 8851 |             { | 
 | 8852 |               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P); | 
 | 8853 |               plci->NData[0].PLength = data->Length; | 
 | 8854 |               if (data->Flags & 0x10) | 
 | 8855 |                 plci->NL.Req = plci->nl_req = (byte)N_UDATA; | 
 | 8856 |  | 
 | 8857 |               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01)) | 
 | 8858 |                 plci->NL.Req = plci->nl_req = (byte)N_BDATA; | 
 | 8859 |  | 
 | 8860 |               else | 
 | 8861 |                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA); | 
 | 8862 |             } | 
 | 8863 |             plci->NL.X = plci->NData; | 
 | 8864 |             plci->NL.ReqCh = a->ncci_ch[ncci]; | 
 | 8865 |             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req)); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 8866 |             plci->data_sent = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8867 |             plci->data_sent_ptr = data->P; | 
 | 8868 |             a->request(&plci->NL); | 
 | 8869 |           } | 
 | 8870 |           else { | 
 | 8871 |             cleanup_ncci_data (plci, ncci); | 
 | 8872 |           } | 
 | 8873 |         } | 
 | 8874 |         else if (plci->send_disc == ncci) | 
 | 8875 |         { | 
 | 8876 |           /* dprintf("N_DISC"); */ | 
 | 8877 |           plci->NData[0].PLength = 0; | 
 | 8878 |           plci->NL.ReqCh = a->ncci_ch[ncci]; | 
 | 8879 |           plci->NL.Req = plci->nl_req = N_DISC; | 
 | 8880 |           a->request(&plci->NL); | 
 | 8881 |           plci->command = _DISCONNECT_B3_R; | 
 | 8882 |           plci->send_disc = 0; | 
 | 8883 |         } | 
 | 8884 |       } | 
 | 8885 |     } while (!plci->nl_req && (ncci != plci->ncci_ring_list)); | 
 | 8886 |     plci->ncci_ring_list = ncci; | 
 | 8887 |   } | 
 | 8888 | } | 
 | 8889 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 8890 | static void listen_check(DIVA_CAPI_ADAPTER *a) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8891 | { | 
 | 8892 |   word i,j; | 
 | 8893 |   PLCI   * plci; | 
 | 8894 |   byte activnotifiedcalls = 0; | 
 | 8895 |  | 
 | 8896 |   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen)); | 
 | 8897 |   if (!remove_started && !a->adapter_disabled) | 
 | 8898 |   { | 
 | 8899 |     for(i=0;i<a->max_plci;i++) | 
 | 8900 |     { | 
 | 8901 |       plci = &(a->plci[i]); | 
 | 8902 |       if(plci->notifiedcall) activnotifiedcalls++; | 
 | 8903 |     } | 
 | 8904 |     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls)); | 
 | 8905 |  | 
 | 8906 |     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) { | 
 | 8907 |       if((j=get_plci(a))) { | 
 | 8908 |         a->listen_active++; | 
 | 8909 |         plci = &a->plci[j-1]; | 
 | 8910 |         plci->State = LISTENING; | 
 | 8911 |  | 
 | 8912 |         add_p(plci,OAD,"\x01\xfd"); | 
 | 8913 |  | 
 | 8914 |         add_p(plci,KEY,"\x04\x43\x41\x32\x30"); | 
 | 8915 |  | 
 | 8916 |         add_p(plci,CAI,"\x01\xc0"); | 
 | 8917 |         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 8918 |         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */        | 
 | 8919 |         add_p(plci,SHIFT|6,NULL); | 
 | 8920 |         add_p(plci,SIN,"\x02\x00\x00"); | 
 | 8921 |         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */ | 
 | 8922 |         sig_req(plci,ASSIGN,DSIG_ID); | 
 | 8923 |         send_req(plci); | 
 | 8924 |       } | 
 | 8925 |     } | 
 | 8926 |   } | 
 | 8927 | } | 
 | 8928 |  | 
 | 8929 | /*------------------------------------------------------------------*/ | 
 | 8930 | /* functions for all parameters sent in INDs                        */ | 
 | 8931 | /*------------------------------------------------------------------*/ | 
 | 8932 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 8933 | static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8934 | { | 
 | 8935 |   word ploc;            /* points to current location within packet */ | 
 | 8936 |   byte w; | 
 | 8937 |   byte wlen; | 
 | 8938 |   byte codeset,lock; | 
 | 8939 |   byte   * in; | 
 | 8940 |   word i; | 
 | 8941 |   word code; | 
 | 8942 |   word mIEindex = 0; | 
 | 8943 |   ploc = 0; | 
 | 8944 |   codeset = 0; | 
 | 8945 |   lock = 0; | 
 | 8946 |  | 
 | 8947 |   in = plci->Sig.RBuffer->P; | 
 | 8948 |   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */ | 
 | 8949 |   {                            /* element but parms array is larger      */ | 
 | 8950 |     parms[i] = (byte   *)""; | 
 | 8951 |   } | 
 | 8952 |   for(i=0; i<multiIEsize; i++) | 
 | 8953 |   { | 
 | 8954 |     parms[i] = (byte   *)""; | 
 | 8955 |   } | 
 | 8956 |  | 
 | 8957 |   while(ploc<plci->Sig.RBuffer->length-1) { | 
 | 8958 |  | 
 | 8959 |         /* read information element id and length                   */ | 
 | 8960 |     w = in[ploc]; | 
 | 8961 |  | 
 | 8962 |     if(w & 0x80) { | 
 | 8963 | /*    w &=0xf0; removed, cannot detect congestion levels */ | 
 | 8964 | /*    upper 4 bit masked with w==SHIFT now               */ | 
 | 8965 |       wlen = 0; | 
 | 8966 |     } | 
 | 8967 |     else { | 
 | 8968 |       wlen = (byte)(in[ploc+1]+1); | 
 | 8969 |     } | 
 | 8970 |         /* check if length valid (not exceeding end of packet)      */ | 
 | 8971 |     if((ploc+wlen) > 270) return ; | 
 | 8972 |     if(lock & 0x80) lock &=0x7f; | 
 | 8973 |     else codeset = lock; | 
 | 8974 |  | 
 | 8975 |     if((w&0xf0)==SHIFT) { | 
 | 8976 |       codeset = in[ploc]; | 
 | 8977 |       if(!(codeset & 0x08)) lock = (byte)(codeset & 7); | 
 | 8978 |       codeset &=7; | 
 | 8979 |       lock |=0x80; | 
 | 8980 |     } | 
 | 8981 |     else { | 
 | 8982 |       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800; | 
 | 8983 |       else code = w; | 
 | 8984 |       code |= (codeset<<8); | 
 | 8985 |  | 
 | 8986 |       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++); | 
 | 8987 |  | 
 | 8988 |       if(i<parms_id[0]+1) { | 
 | 8989 |         if(!multiIEsize) { /* with multiIEs use next field index,          */ | 
 | 8990 |           mIEindex = i-1;    /* with normal IEs use same index like parms_id */ | 
 | 8991 |         } | 
 | 8992 |  | 
 | 8993 |         parms[mIEindex] = &in[ploc+1]; | 
 | 8994 |         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc])); | 
 | 8995 |         if(parms_id[i]==OAD | 
 | 8996 |         || parms_id[i]==CONN_NR | 
 | 8997 |         || parms_id[i]==CAD) { | 
 | 8998 |           if(in[ploc+2] &0x80) { | 
 | 8999 |             in[ploc+0] = (byte)(in[ploc+1]+1); | 
 | 9000 |             in[ploc+1] = (byte)(in[ploc+2] &0x7f); | 
 | 9001 |             in[ploc+2] = 0x80; | 
 | 9002 |             parms[mIEindex] = &in[ploc]; | 
 | 9003 |           } | 
 | 9004 |         } | 
 | 9005 |         mIEindex++;       /* effects multiIEs only */ | 
 | 9006 |       } | 
 | 9007 |     } | 
 | 9008 |  | 
 | 9009 |     ploc +=(wlen+1); | 
 | 9010 |   } | 
 | 9011 |   return ; | 
 | 9012 | } | 
 | 9013 |  | 
 | 9014 | /*------------------------------------------------------------------*/ | 
 | 9015 | /* try to match a cip from received BC and HLC                      */ | 
 | 9016 | /*------------------------------------------------------------------*/ | 
 | 9017 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 9018 | static byte ie_compare(byte *ie1, byte *ie2) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9019 | { | 
 | 9020 |   word i; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9021 |   if(!ie1 || ! ie2) return false; | 
 | 9022 |   if(!ie1[0]) return false; | 
 | 9023 |   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false; | 
 | 9024 |   return true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9025 | } | 
 | 9026 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 9027 | static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9028 | { | 
 | 9029 |   word i; | 
 | 9030 |   word j; | 
 | 9031 |  | 
 | 9032 |   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--); | 
 | 9033 |  | 
 | 9034 |   for(j=16;j<29 && | 
 | 9035 |            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++); | 
 | 9036 |   if(j==29) return i; | 
 | 9037 |   return j; | 
 | 9038 | } | 
 | 9039 |  | 
 | 9040 |  | 
 | 9041 | static byte AddInfo(byte   **add_i, | 
 | 9042 |                     byte   **fty_i, | 
 | 9043 |                     byte   *esc_chi, | 
 | 9044 |                     byte *facility) | 
 | 9045 | { | 
 | 9046 |   byte i; | 
 | 9047 |   byte j; | 
 | 9048 |   byte k; | 
 | 9049 |   byte flen; | 
 | 9050 |   byte len=0; | 
 | 9051 |    /* facility is a nested structure */ | 
 | 9052 |    /* FTY can be more than once      */ | 
 | 9053 |  | 
| Roel Kluin | 3eb1a6f | 2008-02-06 01:38:30 -0800 | [diff] [blame] | 9054 | 	if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9055 |   { | 
 | 9056 |     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */ | 
 | 9057 |   } | 
 | 9058 |  | 
 | 9059 |   else | 
 | 9060 |   { | 
 | 9061 |     add_i[0] = (byte   *)""; | 
 | 9062 |   } | 
 | 9063 |   if(!fty_i[0][0]) | 
 | 9064 |   { | 
 | 9065 |     add_i[3] = (byte   *)""; | 
 | 9066 |   } | 
 | 9067 |   else | 
 | 9068 |   {    /* facility array found  */ | 
 | 9069 |     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++) | 
 | 9070 |     { | 
 | 9071 |       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0])); | 
 | 9072 |       len += fty_i[i][0]; | 
 | 9073 |       len += 2; | 
 | 9074 |       flen=fty_i[i][0]; | 
 | 9075 |       facility[j++]=0x1c; /* copy fac IE */ | 
 | 9076 |       for(k=0;k<=flen;k++,j++) | 
 | 9077 |       { | 
 | 9078 |         facility[j]=fty_i[i][k]; | 
 | 9079 | /*      dbug(1,dprintf("%x ",facility[j])); */ | 
 | 9080 |       } | 
 | 9081 |     } | 
 | 9082 |     facility[0] = len; | 
 | 9083 |     add_i[3] = facility; | 
 | 9084 |   } | 
 | 9085 | /*  dbug(1,dprintf("FacArrLen=%d ",len)); */ | 
 | 9086 |   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0]; | 
 | 9087 |   len += 4;                          /* calculate length of all */ | 
 | 9088 |   return(len); | 
 | 9089 | } | 
 | 9090 |  | 
 | 9091 | /*------------------------------------------------------------------*/ | 
 | 9092 | /* voice and codec features                                         */ | 
 | 9093 | /*------------------------------------------------------------------*/ | 
 | 9094 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 9095 | static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9096 | { | 
 | 9097 |   byte voice_chi[] = "\x02\x18\x01"; | 
 | 9098 |   byte channel; | 
 | 9099 |  | 
 | 9100 |   channel = chi[chi[0]]&0x3; | 
 | 9101 |   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel)); | 
 | 9102 |   voice_chi[2] = (channel) ? channel : 1; | 
 | 9103 |   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */ | 
 | 9104 |   add_p(plci,ESC,voice_chi);                  /* Channel */ | 
 | 9105 |   sig_req(plci,TEL_CTRL,0); | 
 | 9106 |   send_req(plci); | 
 | 9107 |   if(a->AdvSignalPLCI) | 
 | 9108 |   { | 
 | 9109 |     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION); | 
 | 9110 |   } | 
 | 9111 | } | 
 | 9112 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 9113 | static void VoiceChannelOff(PLCI *plci) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9114 | { | 
 | 9115 |   dbug(1,dprintf("ExtDevOFF")); | 
 | 9116 |   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */ | 
 | 9117 |   sig_req(plci,TEL_CTRL,0); | 
 | 9118 |   send_req(plci); | 
 | 9119 |   if(plci->adapter->AdvSignalPLCI) | 
 | 9120 |   { | 
 | 9121 |     adv_voice_clear_config (plci->adapter->AdvSignalPLCI); | 
 | 9122 |   } | 
 | 9123 | } | 
 | 9124 |  | 
 | 9125 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 9126 | static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, | 
 | 9127 | 			    byte hook_listen) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9128 | { | 
 | 9129 |   word j; | 
 | 9130 |   PLCI   *splci; | 
 | 9131 |  | 
 | 9132 |   /* check if hardware supports handset with hook states (adv.codec) */ | 
 | 9133 |   /* or if just a on board codec is supported                        */ | 
 | 9134 |   /* the advanced codec plci is just for internal use                */ | 
 | 9135 |  | 
 | 9136 |   /* diva Pro with on-board codec:                                   */ | 
 | 9137 |   if(a->profile.Global_Options & HANDSET) | 
 | 9138 |   { | 
 | 9139 |     /* new call, but hook states are already signalled */ | 
 | 9140 |     if(a->AdvCodecFLAG) | 
 | 9141 |     { | 
 | 9142 |       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI) | 
 | 9143 |       { | 
 | 9144 |         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI)); | 
 | 9145 |         return 0x2001; /* codec in use by another application */ | 
 | 9146 |       } | 
| Harvey Harrison | dd58c0d | 2008-04-28 02:14:39 -0700 | [diff] [blame] | 9147 |       if(plci!=NULL) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9148 |       { | 
 | 9149 |         a->AdvSignalPLCI = plci; | 
 | 9150 |         plci->tel=ADV_VOICE; | 
 | 9151 |       } | 
 | 9152 |       return 0;                      /* adv codec still used */ | 
 | 9153 |     } | 
 | 9154 |     if((j=get_plci(a))) | 
 | 9155 |     { | 
 | 9156 |       splci = &a->plci[j-1]; | 
 | 9157 |       splci->tel = CODEC_PERMANENT; | 
 | 9158 |       /* hook_listen indicates if a facility_req with handset/hook support */ | 
 | 9159 |       /* was sent. Otherwise if just a call on an external device was made */ | 
 | 9160 |       /* the codec will be used but the hook info will be discarded (just  */ | 
 | 9161 |       /* the external controller is in use                                 */ | 
 | 9162 |       if(hook_listen) splci->State = ADVANCED_VOICE_SIG; | 
 | 9163 |       else | 
 | 9164 |       { | 
 | 9165 |         splci->State = ADVANCED_VOICE_NOSIG; | 
 | 9166 |         if(plci) | 
 | 9167 |         { | 
 | 9168 |           plci->spoofed_msg = SPOOFING_REQUIRED; | 
 | 9169 |         } | 
 | 9170 |                                                /* indicate D-ch connect if  */ | 
 | 9171 |       }                                        /* codec is connected OK     */ | 
| Harvey Harrison | dd58c0d | 2008-04-28 02:14:39 -0700 | [diff] [blame] | 9172 |       if(plci!=NULL) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9173 |       { | 
 | 9174 |         a->AdvSignalPLCI = plci; | 
 | 9175 |         plci->tel=ADV_VOICE; | 
 | 9176 |       } | 
 | 9177 |       a->AdvSignalAppl = appl; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9178 |       a->AdvCodecFLAG = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9179 |       a->AdvCodecPLCI = splci; | 
 | 9180 |       add_p(splci,CAI,"\x01\x15"); | 
 | 9181 |       add_p(splci,LLI,"\x01\x00"); | 
 | 9182 |       add_p(splci,ESC,"\x02\x18\x00"); | 
 | 9183 |       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 9184 |       splci->internal_command = PERM_COD_ASSIGN; | 
 | 9185 |       dbug(1,dprintf("Codec Assign")); | 
 | 9186 |       sig_req(splci,ASSIGN,DSIG_ID); | 
 | 9187 |       send_req(splci); | 
 | 9188 |     } | 
 | 9189 |     else | 
 | 9190 |     { | 
 | 9191 |       return 0x2001; /* wrong state, no more plcis */ | 
 | 9192 |     } | 
 | 9193 |   } | 
 | 9194 |   else if(a->profile.Global_Options & ON_BOARD_CODEC) | 
 | 9195 |   { | 
 | 9196 |     if(hook_listen) return 0x300B;               /* Facility not supported */ | 
 | 9197 |                                                  /* no hook with SCOM      */ | 
| Harvey Harrison | dd58c0d | 2008-04-28 02:14:39 -0700 | [diff] [blame] | 9198 |     if(plci!=NULL) plci->tel = CODEC; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9199 |     dbug(1,dprintf("S/SCOM codec")); | 
 | 9200 |     /* first time we use the scom-s codec we must shut down the internal   */ | 
 | 9201 |     /* handset application of the card. This can be done by an assign with */ | 
 | 9202 |     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/ | 
 | 9203 |     if(!a->scom_appl_disable){ | 
 | 9204 |       if((j=get_plci(a))) { | 
 | 9205 |         splci = &a->plci[j-1]; | 
 | 9206 |         add_p(splci,CAI,"\x01\x80"); | 
 | 9207 |         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 9208 |         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */ | 
 | 9209 |         send_req(splci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9210 |         a->scom_appl_disable = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9211 |       } | 
 | 9212 |       else{ | 
 | 9213 |         return 0x2001; /* wrong state, no more plcis */ | 
 | 9214 |       } | 
 | 9215 |     } | 
 | 9216 |   } | 
 | 9217 |   else return 0x300B;               /* Facility not supported */ | 
 | 9218 |  | 
 | 9219 |   return 0; | 
 | 9220 | } | 
 | 9221 |  | 
 | 9222 |  | 
| Hannes Eder | 4ee59d5 | 2008-12-16 01:17:33 -0800 | [diff] [blame] | 9223 | static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9224 | { | 
 | 9225 |  | 
 | 9226 |   dbug(1,dprintf("CodecIdCheck")); | 
 | 9227 |  | 
 | 9228 |   if(a->AdvSignalPLCI == plci) | 
 | 9229 |   { | 
 | 9230 |     dbug(1,dprintf("PLCI owns codec")); | 
 | 9231 |     VoiceChannelOff(a->AdvCodecPLCI); | 
 | 9232 |     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG) | 
 | 9233 |     { | 
 | 9234 |       dbug(1,dprintf("remove temp codec PLCI")); | 
 | 9235 |       plci_remove(a->AdvCodecPLCI); | 
 | 9236 |       a->AdvCodecFLAG  = 0; | 
 | 9237 |       a->AdvCodecPLCI  = NULL; | 
 | 9238 |       a->AdvSignalAppl = NULL; | 
 | 9239 |     } | 
 | 9240 |     a->AdvSignalPLCI = NULL; | 
 | 9241 |   } | 
 | 9242 | } | 
 | 9243 |  | 
 | 9244 | /* ------------------------------------------------------------------- | 
 | 9245 |     Ask for physical address of card on PCI bus | 
 | 9246 |    ------------------------------------------------------------------- */ | 
 | 9247 | static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a, | 
 | 9248 |                                         IDI_SYNC_REQ  * preq) { | 
 | 9249 |   a->sdram_bar = 0; | 
 | 9250 |   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) { | 
 | 9251 |     ENTITY   * e = (ENTITY   *)preq; | 
 | 9252 |  | 
 | 9253 |     e->user[0] = a->Id - 1; | 
 | 9254 |     preq->xdi_sdram_bar.info.bar    = 0; | 
 | 9255 |     preq->xdi_sdram_bar.Req         = 0; | 
 | 9256 |     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR; | 
 | 9257 |  | 
 | 9258 |     (*(a->request))(e); | 
 | 9259 |  | 
 | 9260 |     a->sdram_bar = preq->xdi_sdram_bar.info.bar; | 
 | 9261 |     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar)); | 
 | 9262 |   } | 
 | 9263 | } | 
 | 9264 |  | 
 | 9265 | /* ------------------------------------------------------------------- | 
 | 9266 |      Ask XDI about extended features | 
 | 9267 |    ------------------------------------------------------------------- */ | 
 | 9268 | static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) { | 
 | 9269 |   IDI_SYNC_REQ   * preq; | 
 | 9270 |     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)]; | 
 | 9271 |  | 
 | 9272 |     char features[4]; | 
 | 9273 |   preq = (IDI_SYNC_REQ   *)&buffer[0]; | 
 | 9274 |  | 
 | 9275 |   if (!diva_xdi_extended_features) { | 
 | 9276 |     ENTITY   * e = (ENTITY   *)preq; | 
 | 9277 |     diva_xdi_extended_features |= 0x80000000; | 
 | 9278 |  | 
 | 9279 |     e->user[0] = a->Id - 1; | 
 | 9280 |     preq->xdi_extended_features.Req = 0; | 
 | 9281 |     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES; | 
 | 9282 |     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features); | 
 | 9283 |     preq->xdi_extended_features.info.features = &features[0]; | 
 | 9284 |  | 
 | 9285 |     (*(a->request))(e); | 
 | 9286 |  | 
 | 9287 |     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) { | 
 | 9288 |       /* | 
 | 9289 |          Check features located in the byte '0' | 
 | 9290 |          */ | 
 | 9291 |       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) { | 
 | 9292 |         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA; | 
 | 9293 |       } | 
 | 9294 |       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) { | 
 | 9295 |         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA; | 
 | 9296 |         dbug(1,dprintf("XDI provides RxDMA")); | 
 | 9297 |       } | 
 | 9298 |       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) { | 
 | 9299 |         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR; | 
 | 9300 |       } | 
 | 9301 |       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) { | 
 | 9302 |         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL; | 
 | 9303 |         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature")); | 
 | 9304 |       } | 
 | 9305 |  | 
 | 9306 |     } | 
 | 9307 |   } | 
 | 9308 |  | 
 | 9309 |   diva_ask_for_xdi_sdram_bar (a, preq); | 
 | 9310 | } | 
 | 9311 |  | 
 | 9312 | /*------------------------------------------------------------------*/ | 
 | 9313 | /* automatic law                                                    */ | 
 | 9314 | /*------------------------------------------------------------------*/ | 
 | 9315 | /* called from OS specific part after init time to get the Law              */ | 
 | 9316 | /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */ | 
 | 9317 | void AutomaticLaw(DIVA_CAPI_ADAPTER   *a) | 
 | 9318 | { | 
 | 9319 |   word j; | 
 | 9320 |   PLCI   *splci; | 
 | 9321 |  | 
 | 9322 |   if(a->automatic_law) { | 
 | 9323 |     return; | 
 | 9324 |   } | 
 | 9325 |   if((j=get_plci(a))) { | 
 | 9326 |     diva_get_extended_adapter_features (a); | 
 | 9327 |     splci = &a->plci[j-1]; | 
 | 9328 |     a->automatic_lawPLCI = splci; | 
 | 9329 |     a->automatic_law = 1; | 
 | 9330 |     add_p(splci,CAI,"\x01\x80"); | 
 | 9331 |     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 9332 |     splci->internal_command = USELAW_REQ; | 
 | 9333 |     splci->command = 0; | 
 | 9334 |     splci->number = 0; | 
 | 9335 |     sig_req(splci,ASSIGN,DSIG_ID); | 
 | 9336 |     send_req(splci); | 
 | 9337 |   } | 
 | 9338 | } | 
 | 9339 |  | 
 | 9340 | /* called from OS specific part if an application sends an Capi20Release */ | 
 | 9341 | word CapiRelease(word Id) | 
 | 9342 | { | 
 | 9343 |   word i, j, appls_found; | 
 | 9344 |   PLCI   *plci; | 
 | 9345 |   APPL   *this; | 
 | 9346 |   DIVA_CAPI_ADAPTER   *a; | 
 | 9347 |  | 
 | 9348 |   if (!Id) | 
 | 9349 |   { | 
 | 9350 |     dbug(0,dprintf("A: CapiRelease(Id==0)")); | 
 | 9351 |     return (_WRONG_APPL_ID); | 
 | 9352 |   } | 
 | 9353 |  | 
 | 9354 |   this = &application[Id-1];               /* get application pointer */ | 
 | 9355 |  | 
 | 9356 |   for(i=0,appls_found=0; i<max_appl; i++) | 
 | 9357 |   { | 
 | 9358 |     if(application[i].Id)       /* an application has been found        */ | 
 | 9359 |     { | 
 | 9360 |       appls_found++; | 
 | 9361 |     } | 
 | 9362 |   } | 
 | 9363 |  | 
 | 9364 |   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */ | 
 | 9365 |   { | 
 | 9366 |     a = &adapter[i]; | 
 | 9367 |     if (a->request) | 
 | 9368 |     { | 
 | 9369 |       a->Info_Mask[Id-1] = 0; | 
 | 9370 |       a->CIP_Mask[Id-1] = 0; | 
 | 9371 |       a->Notification_Mask[Id-1] = 0; | 
 | 9372 |       a->codec_listen[Id-1] = NULL; | 
 | 9373 |       a->requested_options_table[Id-1] = 0; | 
 | 9374 |       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */ | 
 | 9375 |       {                                      /* with this application   */ | 
 | 9376 |         plci = &a->plci[j]; | 
 | 9377 |         if(plci->Id)                         /* if plci owns no application */ | 
 | 9378 |         {                                    /* it may be not jet connected */ | 
 | 9379 |           if(plci->State==INC_CON_PENDING | 
 | 9380 |           || plci->State==INC_CON_ALERT) | 
 | 9381 |           { | 
 | 9382 |             if(test_c_ind_mask_bit (plci, (word)(Id-1))) | 
 | 9383 |             { | 
 | 9384 |               clear_c_ind_mask_bit (plci, (word)(Id-1)); | 
 | 9385 |               if(c_ind_mask_empty (plci)) | 
 | 9386 |               { | 
 | 9387 |                 sig_req(plci,HANGUP,0); | 
 | 9388 |                 send_req(plci); | 
 | 9389 |                 plci->State = OUTG_DIS_PENDING; | 
 | 9390 |               } | 
 | 9391 |             } | 
 | 9392 |           } | 
 | 9393 |           if(test_c_ind_mask_bit (plci, (word)(Id-1))) | 
 | 9394 |           { | 
 | 9395 |             clear_c_ind_mask_bit (plci, (word)(Id-1)); | 
 | 9396 |             if(c_ind_mask_empty (plci)) | 
 | 9397 |             { | 
 | 9398 |               if(!plci->appl) | 
 | 9399 |               { | 
 | 9400 |                 plci_remove(plci); | 
 | 9401 |                 plci->State = IDLE; | 
 | 9402 |               } | 
 | 9403 |             } | 
 | 9404 |           } | 
 | 9405 |           if(plci->appl==this) | 
 | 9406 |           { | 
 | 9407 |             plci->appl = NULL; | 
 | 9408 |             plci_remove(plci); | 
 | 9409 |             plci->State = IDLE; | 
 | 9410 |           } | 
 | 9411 |         } | 
 | 9412 |       } | 
 | 9413 |       listen_check(a); | 
 | 9414 |  | 
 | 9415 |       if(a->flag_dynamic_l1_down) | 
 | 9416 |       { | 
 | 9417 |         if(appls_found==1)            /* last application does a capi release */ | 
 | 9418 |         { | 
 | 9419 |           if((j=get_plci(a))) | 
 | 9420 |           { | 
 | 9421 |             plci = &a->plci[j-1]; | 
 | 9422 |             plci->command = 0; | 
 | 9423 |             add_p(plci,OAD,"\x01\xfd"); | 
 | 9424 |             add_p(plci,CAI,"\x01\x80"); | 
 | 9425 |             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 9426 |             add_p(plci,SHIFT|6,NULL); | 
 | 9427 |             add_p(plci,SIN,"\x02\x00\x00"); | 
 | 9428 |             plci->internal_command = REM_L1_SIG_ASSIGN_PEND; | 
 | 9429 |             sig_req(plci,ASSIGN,DSIG_ID); | 
 | 9430 |             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */ | 
 | 9431 |             sig_req(plci,SIG_CTRL,0); | 
 | 9432 |             send_req(plci); | 
 | 9433 |           } | 
 | 9434 |         } | 
 | 9435 |       } | 
 | 9436 |       if(a->AdvSignalAppl==this) | 
 | 9437 |       { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9438 |         this->NullCREnable = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9439 |         if (a->AdvCodecPLCI) | 
 | 9440 |         { | 
 | 9441 |           plci_remove(a->AdvCodecPLCI); | 
 | 9442 |           a->AdvCodecPLCI->tel = 0; | 
 | 9443 |           a->AdvCodecPLCI->adv_nl = 0; | 
 | 9444 |         } | 
 | 9445 |         a->AdvSignalAppl = NULL; | 
 | 9446 |         a->AdvSignalPLCI = NULL; | 
 | 9447 |         a->AdvCodecFLAG = 0; | 
 | 9448 |         a->AdvCodecPLCI = NULL; | 
 | 9449 |       } | 
 | 9450 |     } | 
 | 9451 |   } | 
 | 9452 |  | 
 | 9453 |   this->Id = 0; | 
 | 9454 |  | 
 | 9455 |   return GOOD; | 
 | 9456 | } | 
 | 9457 |  | 
 | 9458 | static word plci_remove_check(PLCI   *plci) | 
 | 9459 | { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9460 |   if(!plci) return true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9461 |   if(!plci->NL.Id && c_ind_mask_empty (plci)) | 
 | 9462 |   { | 
 | 9463 |     if(plci->Sig.Id == 0xff) | 
 | 9464 |       plci->Sig.Id = 0; | 
 | 9465 |     if(!plci->Sig.Id) | 
 | 9466 |     { | 
 | 9467 |       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id)); | 
 | 9468 |       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id)); | 
 | 9469 |       if (plci->Id) | 
 | 9470 |       { | 
 | 9471 |         CodecIdCheck(plci->adapter, plci); | 
 | 9472 |         clear_b1_config (plci); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9473 |         ncci_remove (plci, 0, false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9474 |         plci_free_msg_in_queue (plci); | 
 | 9475 |         channel_flow_control_remove (plci); | 
 | 9476 |         plci->Id = 0; | 
 | 9477 |         plci->State = IDLE; | 
 | 9478 |         plci->channels = 0; | 
 | 9479 |         plci->appl = NULL; | 
 | 9480 |         plci->notifiedcall = 0; | 
 | 9481 |       } | 
 | 9482 |       listen_check(plci->adapter); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9483 |       return true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9484 |     } | 
 | 9485 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9486 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9487 | } | 
 | 9488 |  | 
 | 9489 |  | 
 | 9490 | /*------------------------------------------------------------------*/ | 
 | 9491 |  | 
 | 9492 | static byte plci_nl_busy (PLCI   *plci) | 
 | 9493 | { | 
 | 9494 |   /* only applicable for non-multiplexed protocols */ | 
 | 9495 |   return (plci->nl_req | 
 | 9496 |     || (plci->ncci_ring_list | 
 | 9497 |      && plci->adapter->ncci_ch[plci->ncci_ring_list] | 
 | 9498 |      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING))); | 
 | 9499 | } | 
 | 9500 |  | 
 | 9501 |  | 
 | 9502 | /*------------------------------------------------------------------*/ | 
 | 9503 | /* DTMF facilities                                                  */ | 
 | 9504 | /*------------------------------------------------------------------*/ | 
 | 9505 |  | 
 | 9506 |  | 
 | 9507 | static struct | 
 | 9508 | { | 
 | 9509 |   byte send_mask; | 
 | 9510 |   byte listen_mask; | 
 | 9511 |   byte character; | 
 | 9512 |   byte code; | 
 | 9513 | } dtmf_digit_map[] = | 
 | 9514 | { | 
 | 9515 |   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK }, | 
 | 9516 |   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR }, | 
 | 9517 |   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 }, | 
 | 9518 |   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 }, | 
 | 9519 |   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 }, | 
 | 9520 |   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 }, | 
 | 9521 |   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 }, | 
 | 9522 |   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 }, | 
 | 9523 |   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 }, | 
 | 9524 |   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 }, | 
 | 9525 |   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 }, | 
 | 9526 |   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 }, | 
 | 9527 |   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A }, | 
 | 9528 |   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B }, | 
 | 9529 |   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C }, | 
 | 9530 |   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D }, | 
 | 9531 |   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A }, | 
 | 9532 |   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B }, | 
 | 9533 |   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C }, | 
 | 9534 |   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D }, | 
 | 9535 |  | 
 | 9536 |   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE }, | 
 | 9537 |   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE }, | 
 | 9538 |   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE }, | 
 | 9539 |   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE }, | 
 | 9540 |   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE }, | 
 | 9541 |   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE }, | 
 | 9542 |   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE }, | 
 | 9543 |   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE }, | 
 | 9544 |   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE }, | 
 | 9545 |   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE }, | 
 | 9546 |   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE }, | 
 | 9547 |   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE }, | 
 | 9548 |   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE }, | 
 | 9549 |   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE }, | 
 | 9550 |   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE }, | 
 | 9551 |   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE }, | 
 | 9552 |   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE }, | 
 | 9553 |   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE }, | 
 | 9554 |   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE }, | 
 | 9555 |   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE }, | 
 | 9556 |   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE }, | 
 | 9557 |   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE }, | 
 | 9558 |   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE }, | 
 | 9559 |   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL }, | 
 | 9560 |   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE }, | 
 | 9561 |   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE }, | 
 | 9562 |   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE }, | 
 | 9563 |   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE }, | 
 | 9564 |   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE }, | 
 | 9565 |   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE }, | 
 | 9566 |   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE }, | 
 | 9567 |   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE }, | 
 | 9568 |   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE }, | 
 | 9569 |   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS }, | 
 | 9570 |   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID }, | 
 | 9571 |   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH }, | 
 | 9572 |   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 }, | 
 | 9573 |   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 }, | 
 | 9574 |   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 }, | 
 | 9575 |   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 }, | 
 | 9576 |   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 }, | 
 | 9577 |   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 }, | 
 | 9578 |   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 }, | 
 | 9579 |   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 }, | 
 | 9580 |   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 }, | 
 | 9581 |   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 }, | 
 | 9582 |   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 }, | 
 | 9583 |   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 }, | 
 | 9584 |   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 }, | 
 | 9585 |   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP }, | 
 | 9586 |   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 }, | 
 | 9587 |   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST }, | 
 | 9588 |  | 
 | 9589 | }; | 
 | 9590 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 9591 | #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9592 |  | 
 | 9593 |  | 
 | 9594 | static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask) | 
 | 9595 | { | 
 | 9596 |   word min_digit_duration, min_gap_duration; | 
 | 9597 |  | 
 | 9598 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x", | 
 | 9599 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 9600 |     (char   *)(FILE_), __LINE__, enable_mask)); | 
 | 9601 |  | 
 | 9602 |   if (enable_mask != 0) | 
 | 9603 |   { | 
 | 9604 |     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms; | 
 | 9605 |     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms; | 
 | 9606 |     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER; | 
 | 9607 |     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration); | 
 | 9608 |     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration); | 
 | 9609 |     plci->NData[0].PLength = 5; | 
 | 9610 |  | 
 | 9611 |     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE); | 
 | 9612 |     plci->NData[0].PLength += 2; | 
 | 9613 |     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration); | 
 | 9614 |  | 
 | 9615 |   } | 
 | 9616 |   else | 
 | 9617 |   { | 
 | 9618 |     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER; | 
 | 9619 |     plci->NData[0].PLength = 1; | 
 | 9620 |  | 
 | 9621 |     capidtmf_recv_disable (&(plci->capidtmf_state)); | 
 | 9622 |  | 
 | 9623 |   } | 
 | 9624 |   plci->NData[0].P = plci->internal_req_buffer; | 
 | 9625 |   plci->NL.X = plci->NData; | 
 | 9626 |   plci->NL.ReqCh = 0; | 
 | 9627 |   plci->NL.Req = plci->nl_req = (byte) N_UDATA; | 
 | 9628 |   plci->adapter->request (&plci->NL); | 
 | 9629 | } | 
 | 9630 |  | 
 | 9631 |  | 
 | 9632 | static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count) | 
 | 9633 | { | 
 | 9634 |   word w, i; | 
 | 9635 |  | 
 | 9636 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d", | 
 | 9637 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 9638 |     (char   *)(FILE_), __LINE__, digit_count)); | 
 | 9639 |  | 
 | 9640 |   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS; | 
 | 9641 |   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms; | 
 | 9642 |   PUT_WORD (&plci->internal_req_buffer[1], w); | 
 | 9643 |   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms; | 
 | 9644 |   PUT_WORD (&plci->internal_req_buffer[3], w); | 
 | 9645 |   for (i = 0; i < digit_count; i++) | 
 | 9646 |   { | 
 | 9647 |     w = 0; | 
 | 9648 |     while ((w < DTMF_DIGIT_MAP_ENTRIES) | 
 | 9649 |       && (digit_buffer[i] != dtmf_digit_map[w].character)) | 
 | 9650 |     { | 
 | 9651 |       w++; | 
 | 9652 |     } | 
 | 9653 |     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ? | 
 | 9654 |       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR; | 
 | 9655 |   } | 
 | 9656 |   plci->NData[0].PLength = 5 + digit_count; | 
 | 9657 |   plci->NData[0].P = plci->internal_req_buffer; | 
 | 9658 |   plci->NL.X = plci->NData; | 
 | 9659 |   plci->NL.ReqCh = 0; | 
 | 9660 |   plci->NL.Req = plci->nl_req = (byte) N_UDATA; | 
 | 9661 |   plci->adapter->request (&plci->NL); | 
 | 9662 | } | 
 | 9663 |  | 
 | 9664 |  | 
 | 9665 | static void dtmf_rec_clear_config (PLCI   *plci) | 
 | 9666 | { | 
 | 9667 |  | 
 | 9668 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config", | 
 | 9669 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 9670 |     (char   *)(FILE_), __LINE__)); | 
 | 9671 |  | 
 | 9672 |   plci->dtmf_rec_active = 0; | 
 | 9673 |   plci->dtmf_rec_pulse_ms = 0; | 
 | 9674 |   plci->dtmf_rec_pause_ms = 0; | 
 | 9675 |  | 
 | 9676 |   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law); | 
 | 9677 |  | 
 | 9678 | } | 
 | 9679 |  | 
 | 9680 |  | 
 | 9681 | static void dtmf_send_clear_config (PLCI   *plci) | 
 | 9682 | { | 
 | 9683 |  | 
 | 9684 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config", | 
 | 9685 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 9686 |     (char   *)(FILE_), __LINE__)); | 
 | 9687 |  | 
 | 9688 |   plci->dtmf_send_requests = 0; | 
 | 9689 |   plci->dtmf_send_pulse_ms = 0; | 
 | 9690 |   plci->dtmf_send_pause_ms = 0; | 
 | 9691 | } | 
 | 9692 |  | 
 | 9693 |  | 
 | 9694 | static void dtmf_prepare_switch (dword Id, PLCI   *plci) | 
 | 9695 | { | 
 | 9696 |  | 
 | 9697 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch", | 
 | 9698 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9699 |  | 
 | 9700 |   while (plci->dtmf_send_requests != 0) | 
 | 9701 |     dtmf_confirmation (Id, plci); | 
 | 9702 | } | 
 | 9703 |  | 
 | 9704 |  | 
 | 9705 | static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc) | 
 | 9706 | { | 
 | 9707 |  | 
 | 9708 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d", | 
 | 9709 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 9710 |  | 
 | 9711 |   return (GOOD); | 
 | 9712 | } | 
 | 9713 |  | 
 | 9714 |  | 
 | 9715 | static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc) | 
 | 9716 | { | 
 | 9717 |   word Info; | 
 | 9718 |  | 
 | 9719 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d", | 
 | 9720 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 9721 |  | 
 | 9722 |   Info = GOOD; | 
 | 9723 |   if (plci->B1_facilities & B1_FACILITY_DTMFR) | 
 | 9724 |   { | 
 | 9725 |     switch (plci->adjust_b_state) | 
 | 9726 |     { | 
 | 9727 |     case ADJUST_B_RESTORE_DTMF_1: | 
 | 9728 |       plci->internal_command = plci->adjust_b_command; | 
 | 9729 |       if (plci_nl_busy (plci)) | 
 | 9730 |       { | 
 | 9731 |         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | 
 | 9732 |         break; | 
 | 9733 |       } | 
 | 9734 |       dtmf_enable_receiver (plci, plci->dtmf_rec_active); | 
 | 9735 |       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2; | 
 | 9736 |       break; | 
 | 9737 |     case ADJUST_B_RESTORE_DTMF_2: | 
 | 9738 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 9739 |       { | 
 | 9740 |         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x", | 
 | 9741 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 9742 |         Info = _WRONG_STATE; | 
 | 9743 |         break; | 
 | 9744 |       } | 
 | 9745 |       break; | 
 | 9746 |     } | 
 | 9747 |   } | 
 | 9748 |   return (Info); | 
 | 9749 | } | 
 | 9750 |  | 
 | 9751 |  | 
 | 9752 | static void dtmf_command (dword Id, PLCI   *plci, byte Rc) | 
 | 9753 | { | 
 | 9754 |   word internal_command, Info; | 
 | 9755 |   byte mask; | 
 | 9756 |     byte result[4]; | 
 | 9757 |  | 
 | 9758 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d", | 
 | 9759 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command, | 
 | 9760 |     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms, | 
 | 9761 |     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms)); | 
 | 9762 |  | 
 | 9763 |   Info = GOOD; | 
 | 9764 |   result[0] = 2; | 
 | 9765 |   PUT_WORD (&result[1], DTMF_SUCCESS); | 
 | 9766 |   internal_command = plci->internal_command; | 
 | 9767 |   plci->internal_command = 0; | 
 | 9768 |   mask = 0x01; | 
 | 9769 |   switch (plci->dtmf_cmd) | 
 | 9770 |   { | 
 | 9771 |  | 
 | 9772 |   case DTMF_LISTEN_TONE_START: | 
 | 9773 |     mask <<= 1; | 
 | 9774 |   case DTMF_LISTEN_MF_START: | 
 | 9775 |     mask <<= 1; | 
 | 9776 |  | 
 | 9777 |   case DTMF_LISTEN_START: | 
 | 9778 |     switch (internal_command) | 
 | 9779 |     { | 
 | 9780 |     default: | 
 | 9781 |       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | 
 | 9782 |         B1_FACILITY_DTMFR), DTMF_COMMAND_1); | 
 | 9783 |     case DTMF_COMMAND_1: | 
 | 9784 |       if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 9785 |       { | 
 | 9786 |         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed", | 
 | 9787 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9788 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 9789 |         break; | 
 | 9790 |       } | 
 | 9791 |       if (plci->internal_command) | 
 | 9792 |         return; | 
 | 9793 |     case DTMF_COMMAND_2: | 
 | 9794 |       if (plci_nl_busy (plci)) | 
 | 9795 |       { | 
 | 9796 |         plci->internal_command = DTMF_COMMAND_2; | 
 | 9797 |         return; | 
 | 9798 |       } | 
 | 9799 |       plci->internal_command = DTMF_COMMAND_3; | 
 | 9800 |       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask)); | 
 | 9801 |       return; | 
 | 9802 |     case DTMF_COMMAND_3: | 
 | 9803 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 9804 |       { | 
 | 9805 |         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x", | 
 | 9806 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 9807 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 9808 |         break; | 
 | 9809 |       } | 
 | 9810 |  | 
 | 9811 |       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE; | 
 | 9812 |  | 
 | 9813 |       plci->dtmf_rec_active |= mask; | 
 | 9814 |       break; | 
 | 9815 |     } | 
 | 9816 |     break; | 
 | 9817 |  | 
 | 9818 |  | 
 | 9819 |   case DTMF_LISTEN_TONE_STOP: | 
 | 9820 |     mask <<= 1; | 
 | 9821 |   case DTMF_LISTEN_MF_STOP: | 
 | 9822 |     mask <<= 1; | 
 | 9823 |  | 
 | 9824 |   case DTMF_LISTEN_STOP: | 
 | 9825 |     switch (internal_command) | 
 | 9826 |     { | 
 | 9827 |     default: | 
 | 9828 |       plci->dtmf_rec_active &= ~mask; | 
 | 9829 |       if (plci->dtmf_rec_active) | 
 | 9830 |         break; | 
 | 9831 | /* | 
 | 9832 |     case DTMF_COMMAND_1: | 
 | 9833 |       if (plci->dtmf_rec_active) | 
 | 9834 |       { | 
 | 9835 |         if (plci_nl_busy (plci)) | 
 | 9836 |         { | 
 | 9837 |           plci->internal_command = DTMF_COMMAND_1; | 
 | 9838 |           return; | 
 | 9839 |         } | 
 | 9840 |         plci->dtmf_rec_active &= ~mask; | 
 | 9841 |         plci->internal_command = DTMF_COMMAND_2; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 9842 |         dtmf_enable_receiver (plci, false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9843 |         return; | 
 | 9844 |       } | 
 | 9845 |       Rc = OK; | 
 | 9846 |     case DTMF_COMMAND_2: | 
 | 9847 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 9848 |       { | 
 | 9849 |         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x", | 
 | 9850 |           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc)); | 
 | 9851 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 9852 |         break; | 
 | 9853 |       } | 
 | 9854 | */ | 
 | 9855 |       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities & | 
 | 9856 |         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3); | 
 | 9857 |     case DTMF_COMMAND_3: | 
 | 9858 |       if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 9859 |       { | 
 | 9860 |         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed", | 
 | 9861 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9862 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 9863 |         break; | 
 | 9864 |       } | 
 | 9865 |       if (plci->internal_command) | 
 | 9866 |         return; | 
 | 9867 |       break; | 
 | 9868 |     } | 
 | 9869 |     break; | 
 | 9870 |  | 
 | 9871 |  | 
 | 9872 |   case DTMF_SEND_TONE: | 
 | 9873 |     mask <<= 1; | 
 | 9874 |   case DTMF_SEND_MF: | 
 | 9875 |     mask <<= 1; | 
 | 9876 |  | 
 | 9877 |   case DTMF_DIGITS_SEND: | 
 | 9878 |     switch (internal_command) | 
 | 9879 |     { | 
 | 9880 |     default: | 
 | 9881 |       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | 
 | 9882 |         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)), | 
 | 9883 |         DTMF_COMMAND_1); | 
 | 9884 |     case DTMF_COMMAND_1: | 
 | 9885 |       if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 9886 |       { | 
 | 9887 |         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed", | 
 | 9888 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9889 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 9890 |         break; | 
 | 9891 |       } | 
 | 9892 |       if (plci->internal_command) | 
 | 9893 |         return; | 
 | 9894 |     case DTMF_COMMAND_2: | 
 | 9895 |       if (plci_nl_busy (plci)) | 
 | 9896 |       { | 
 | 9897 |         plci->internal_command = DTMF_COMMAND_2; | 
 | 9898 |         return; | 
 | 9899 |       } | 
 | 9900 |       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number; | 
 | 9901 |       plci->internal_command = DTMF_COMMAND_3; | 
 | 9902 |       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length); | 
 | 9903 |       return; | 
 | 9904 |     case DTMF_COMMAND_3: | 
 | 9905 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 9906 |       { | 
 | 9907 |         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x", | 
 | 9908 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 9909 |         if (plci->dtmf_send_requests != 0) | 
 | 9910 |           (plci->dtmf_send_requests)--; | 
 | 9911 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 9912 |         break; | 
 | 9913 |       } | 
 | 9914 |       return; | 
 | 9915 |     } | 
 | 9916 |     break; | 
 | 9917 |   } | 
 | 9918 |   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number, | 
 | 9919 |     "wws", Info, SELECTOR_DTMF, result); | 
 | 9920 | } | 
 | 9921 |  | 
 | 9922 |  | 
 | 9923 | static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg) | 
 | 9924 | { | 
 | 9925 |   word Info; | 
 | 9926 |   word i, j; | 
 | 9927 |   byte mask; | 
 | 9928 |     API_PARSE dtmf_parms[5]; | 
 | 9929 |     byte result[40]; | 
 | 9930 |  | 
 | 9931 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request", | 
 | 9932 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9933 |  | 
 | 9934 |   Info = GOOD; | 
 | 9935 |   result[0] = 2; | 
 | 9936 |   PUT_WORD (&result[1], DTMF_SUCCESS); | 
 | 9937 |   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED)) | 
 | 9938 |   { | 
 | 9939 |     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | 
 | 9940 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9941 |     Info = _FACILITY_NOT_SUPPORTED; | 
 | 9942 |   } | 
 | 9943 |   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms)) | 
 | 9944 |   { | 
 | 9945 |     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 9946 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9947 |     Info = _WRONG_MESSAGE_FORMAT; | 
 | 9948 |   } | 
 | 9949 |  | 
 | 9950 |   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) | 
 | 9951 |     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES)) | 
 | 9952 |   { | 
 | 9953 |     if (!((a->requested_options_table[appl->Id-1]) | 
 | 9954 |         & (1L << PRIVATE_DTMF_TONE))) | 
 | 9955 |     { | 
 | 9956 |       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | 
 | 9957 |         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); | 
 | 9958 |       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | 
 | 9959 |     } | 
 | 9960 |     else | 
 | 9961 |     { | 
 | 9962 |       for (i = 0; i < 32; i++) | 
 | 9963 |         result[4 + i] = 0; | 
 | 9964 |       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) | 
 | 9965 |       { | 
 | 9966 |         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++) | 
 | 9967 |         { | 
 | 9968 |           if (dtmf_digit_map[i].listen_mask != 0) | 
 | 9969 |             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7)); | 
 | 9970 |         } | 
 | 9971 |       } | 
 | 9972 |       else | 
 | 9973 |       { | 
 | 9974 |         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++) | 
 | 9975 |         { | 
 | 9976 |           if (dtmf_digit_map[i].send_mask != 0) | 
 | 9977 |             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7)); | 
 | 9978 |         } | 
 | 9979 |       } | 
 | 9980 |       result[0] = 3 + 32; | 
 | 9981 |       result[3] = 32; | 
 | 9982 |     } | 
 | 9983 |   } | 
 | 9984 |  | 
 | 9985 |   else if (plci == NULL) | 
 | 9986 |   { | 
 | 9987 |     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | 
 | 9988 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9989 |     Info = _WRONG_IDENTIFIER; | 
 | 9990 |   } | 
 | 9991 |   else | 
 | 9992 |   { | 
 | 9993 |     if (!plci->State | 
 | 9994 |      || !plci->NL.Id || plci->nl_remove_id) | 
 | 9995 |     { | 
 | 9996 |       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | 
 | 9997 |         UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 9998 |       Info = _WRONG_STATE; | 
 | 9999 |     } | 
 | 10000 |     else | 
 | 10001 |     { | 
 | 10002 |       plci->command = 0; | 
 | 10003 |       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info); | 
 | 10004 |       mask = 0x01; | 
 | 10005 |       switch (plci->dtmf_cmd) | 
 | 10006 |       { | 
 | 10007 |  | 
 | 10008 |       case DTMF_LISTEN_TONE_START: | 
 | 10009 |       case DTMF_LISTEN_TONE_STOP: | 
 | 10010 |         mask <<= 1; | 
 | 10011 |       case DTMF_LISTEN_MF_START: | 
 | 10012 |       case DTMF_LISTEN_MF_STOP: | 
 | 10013 |         mask <<= 1; | 
 | 10014 |         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1]) | 
 | 10015 |           & (1L << PRIVATE_DTMF_TONE))) | 
 | 10016 |         { | 
 | 10017 |           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | 
 | 10018 |             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); | 
 | 10019 |           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | 
 | 10020 |           break; | 
 | 10021 |         } | 
 | 10022 |  | 
 | 10023 |       case DTMF_LISTEN_START: | 
 | 10024 |       case DTMF_LISTEN_STOP: | 
 | 10025 |         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF) | 
 | 10026 |          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)) | 
 | 10027 |         { | 
 | 10028 |           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | 
 | 10029 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 10030 |           Info = _FACILITY_NOT_SUPPORTED; | 
 | 10031 |           break; | 
 | 10032 |         } | 
 | 10033 |         if (mask & DTMF_LISTEN_ACTIVE_FLAG) | 
 | 10034 |         { | 
 | 10035 |           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms)) | 
 | 10036 |           { | 
 | 10037 |             plci->dtmf_rec_pulse_ms = 0; | 
 | 10038 |             plci->dtmf_rec_pause_ms = 0; | 
 | 10039 |           } | 
 | 10040 |           else | 
 | 10041 |           { | 
 | 10042 |             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info); | 
 | 10043 |             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info); | 
 | 10044 |           } | 
 | 10045 |         } | 
 | 10046 |         start_internal_command (Id, plci, dtmf_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 10047 |         return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10048 |  | 
 | 10049 |  | 
 | 10050 |       case DTMF_SEND_TONE: | 
 | 10051 |         mask <<= 1; | 
 | 10052 |       case DTMF_SEND_MF: | 
 | 10053 |         mask <<= 1; | 
 | 10054 |         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1]) | 
 | 10055 |           & (1L << PRIVATE_DTMF_TONE))) | 
 | 10056 |         { | 
 | 10057 |           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | 
 | 10058 |             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); | 
 | 10059 |           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | 
 | 10060 |           break; | 
 | 10061 |         } | 
 | 10062 |  | 
 | 10063 |       case DTMF_DIGITS_SEND: | 
 | 10064 |         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms)) | 
 | 10065 |         { | 
 | 10066 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 10067 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 10068 |           Info = _WRONG_MESSAGE_FORMAT; | 
 | 10069 |           break; | 
 | 10070 |         } | 
 | 10071 |         if (mask & DTMF_LISTEN_ACTIVE_FLAG) | 
 | 10072 |         { | 
 | 10073 |           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info); | 
 | 10074 |           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info); | 
 | 10075 |         } | 
 | 10076 |         i = 0; | 
 | 10077 |         j = 0; | 
 | 10078 |         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES)) | 
 | 10079 |         { | 
 | 10080 |           j = 0; | 
 | 10081 |           while ((j < DTMF_DIGIT_MAP_ENTRIES) | 
 | 10082 |             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character) | 
 | 10083 |              || ((dtmf_digit_map[j].send_mask & mask) == 0))) | 
 | 10084 |           { | 
 | 10085 |             j++; | 
 | 10086 |           } | 
 | 10087 |           i++; | 
 | 10088 |         } | 
 | 10089 |         if (j == DTMF_DIGIT_MAP_ENTRIES) | 
 | 10090 |         { | 
 | 10091 |           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x", | 
 | 10092 |             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i])); | 
 | 10093 |           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT); | 
 | 10094 |           break; | 
 | 10095 |         } | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 10096 |         if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10097 |         { | 
 | 10098 |           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun", | 
 | 10099 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 10100 |           Info = _WRONG_STATE; | 
 | 10101 |           break; | 
 | 10102 |         } | 
 | 10103 |         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg); | 
 | 10104 |         start_internal_command (Id, plci, dtmf_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 10105 |         return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10106 |  | 
 | 10107 |       default: | 
 | 10108 |         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | 
 | 10109 |           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd)); | 
 | 10110 |         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | 
 | 10111 |       } | 
 | 10112 |     } | 
 | 10113 |   } | 
 | 10114 |   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | 
 | 10115 |     "wws", Info, SELECTOR_DTMF, result); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 10116 |   return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10117 | } | 
 | 10118 |  | 
 | 10119 |  | 
 | 10120 | static void dtmf_confirmation (dword Id, PLCI   *plci) | 
 | 10121 | { | 
 | 10122 |   word Info; | 
 | 10123 |   word i; | 
 | 10124 |     byte result[4]; | 
 | 10125 |  | 
 | 10126 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation", | 
 | 10127 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 10128 |  | 
 | 10129 |   Info = GOOD; | 
 | 10130 |   result[0] = 2; | 
 | 10131 |   PUT_WORD (&result[1], DTMF_SUCCESS); | 
 | 10132 |   if (plci->dtmf_send_requests != 0) | 
 | 10133 |   { | 
 | 10134 |     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0], | 
 | 10135 |       "wws", GOOD, SELECTOR_DTMF, result); | 
 | 10136 |     (plci->dtmf_send_requests)--; | 
 | 10137 |     for (i = 0; i < plci->dtmf_send_requests; i++) | 
 | 10138 |       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];       | 
 | 10139 |   } | 
 | 10140 | } | 
 | 10141 |  | 
 | 10142 |  | 
 | 10143 | static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length) | 
 | 10144 | { | 
 | 10145 |   word i, j, n; | 
 | 10146 |  | 
 | 10147 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication", | 
 | 10148 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 10149 |  | 
 | 10150 |   n = 0; | 
 | 10151 |   for (i = 1; i < length; i++) | 
 | 10152 |   { | 
 | 10153 |     j = 0; | 
 | 10154 |     while ((j < DTMF_DIGIT_MAP_ENTRIES) | 
 | 10155 |       && ((msg[i] != dtmf_digit_map[j].code) | 
 | 10156 |        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0))) | 
 | 10157 |     { | 
 | 10158 |       j++; | 
 | 10159 |     } | 
 | 10160 |     if (j < DTMF_DIGIT_MAP_ENTRIES) | 
 | 10161 |     { | 
 | 10162 |  | 
 | 10163 |       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG) | 
 | 10164 |        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE) | 
 | 10165 |        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE)) | 
 | 10166 |       { | 
 | 10167 |         if (n + 1 == i) | 
 | 10168 |         { | 
 | 10169 |           for (i = length; i > n + 1; i--) | 
 | 10170 |             msg[i] = msg[i - 1]; | 
 | 10171 |           length++; | 
 | 10172 |           i++; | 
 | 10173 |         } | 
 | 10174 |         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE; | 
 | 10175 |       } | 
 | 10176 |       plci->tone_last_indication_code = dtmf_digit_map[j].character; | 
 | 10177 |  | 
 | 10178 |       msg[++n] = dtmf_digit_map[j].character; | 
 | 10179 |     } | 
 | 10180 |   } | 
 | 10181 |   if (n != 0) | 
 | 10182 |   { | 
 | 10183 |     msg[0] = (byte) n; | 
 | 10184 |     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg); | 
 | 10185 |   } | 
 | 10186 | } | 
 | 10187 |  | 
 | 10188 |  | 
 | 10189 | /*------------------------------------------------------------------*/ | 
 | 10190 | /* DTMF parameters                                                  */ | 
 | 10191 | /*------------------------------------------------------------------*/ | 
 | 10192 |  | 
 | 10193 | static void dtmf_parameter_write (PLCI   *plci) | 
 | 10194 | { | 
 | 10195 |   word i; | 
 | 10196 |     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2]; | 
 | 10197 |  | 
 | 10198 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write", | 
 | 10199 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 10200 |     (char   *)(FILE_), __LINE__)); | 
 | 10201 |  | 
 | 10202 |   parameter_buffer[0] = plci->dtmf_parameter_length + 1; | 
 | 10203 |   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS; | 
 | 10204 |   for (i = 0; i < plci->dtmf_parameter_length; i++) | 
 | 10205 |     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i]; | 
 | 10206 |   add_p (plci, FTY, parameter_buffer); | 
 | 10207 |   sig_req (plci, TEL_CTRL, 0); | 
 | 10208 |   send_req (plci); | 
 | 10209 | } | 
 | 10210 |  | 
 | 10211 |  | 
 | 10212 | static void dtmf_parameter_clear_config (PLCI   *plci) | 
 | 10213 | { | 
 | 10214 |  | 
 | 10215 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config", | 
 | 10216 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 10217 |     (char   *)(FILE_), __LINE__)); | 
 | 10218 |  | 
 | 10219 |   plci->dtmf_parameter_length = 0; | 
 | 10220 | } | 
 | 10221 |  | 
 | 10222 |  | 
 | 10223 | static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci) | 
 | 10224 | { | 
 | 10225 |  | 
 | 10226 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch", | 
 | 10227 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 10228 |  | 
 | 10229 | } | 
 | 10230 |  | 
 | 10231 |  | 
 | 10232 | static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc) | 
 | 10233 | { | 
 | 10234 |  | 
 | 10235 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d", | 
 | 10236 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 10237 |  | 
 | 10238 |   return (GOOD); | 
 | 10239 | } | 
 | 10240 |  | 
 | 10241 |  | 
 | 10242 | static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc) | 
 | 10243 | { | 
 | 10244 |   word Info; | 
 | 10245 |  | 
 | 10246 |   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d", | 
 | 10247 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 10248 |  | 
 | 10249 |   Info = GOOD; | 
 | 10250 |   if ((plci->B1_facilities & B1_FACILITY_DTMFR) | 
 | 10251 |    && (plci->dtmf_parameter_length != 0)) | 
 | 10252 |   { | 
 | 10253 |     switch (plci->adjust_b_state) | 
 | 10254 |     { | 
 | 10255 |     case ADJUST_B_RESTORE_DTMF_PARAMETER_1: | 
 | 10256 |       plci->internal_command = plci->adjust_b_command; | 
 | 10257 |       if (plci->sig_req) | 
 | 10258 |       { | 
 | 10259 |         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1; | 
 | 10260 |         break; | 
 | 10261 |       } | 
 | 10262 |       dtmf_parameter_write (plci); | 
 | 10263 |       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2; | 
 | 10264 |       break; | 
 | 10265 |     case ADJUST_B_RESTORE_DTMF_PARAMETER_2: | 
 | 10266 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 10267 |       { | 
 | 10268 |         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x", | 
 | 10269 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 10270 |         Info = _WRONG_STATE; | 
 | 10271 |         break; | 
 | 10272 |       } | 
 | 10273 |       break; | 
 | 10274 |     } | 
 | 10275 |   } | 
 | 10276 |   return (Info); | 
 | 10277 | } | 
 | 10278 |  | 
 | 10279 |  | 
 | 10280 | /*------------------------------------------------------------------*/ | 
 | 10281 | /* Line interconnect facilities                                     */ | 
 | 10282 | /*------------------------------------------------------------------*/ | 
 | 10283 |  | 
 | 10284 |  | 
 | 10285 | LI_CONFIG   *li_config_table; | 
 | 10286 | word li_total_channels; | 
 | 10287 |  | 
 | 10288 |  | 
 | 10289 | /*------------------------------------------------------------------*/ | 
 | 10290 | /* translate a CHI information element to a channel number          */ | 
 | 10291 | /* returns 0xff - any channel                                       */ | 
 | 10292 | /*         0xfe - chi wrong coding                                  */ | 
 | 10293 | /*         0xfd - D-channel                                         */ | 
 | 10294 | /*         0x00 - no channel                                        */ | 
 | 10295 | /*         else channel number / PRI: timeslot                      */ | 
 | 10296 | /* if channels is provided we accept more than one channel.         */ | 
 | 10297 | /*------------------------------------------------------------------*/ | 
 | 10298 |  | 
 | 10299 | static byte chi_to_channel (byte   *chi, dword *pchannelmap) | 
 | 10300 | { | 
 | 10301 |   int p; | 
 | 10302 |   int i; | 
 | 10303 |   dword map; | 
 | 10304 |   byte excl; | 
 | 10305 |   byte ofs; | 
 | 10306 |   byte ch; | 
 | 10307 |  | 
 | 10308 |   if (pchannelmap) *pchannelmap = 0; | 
 | 10309 |   if(!chi[0]) return 0xff; | 
 | 10310 |   excl = 0; | 
 | 10311 |  | 
 | 10312 |   if(chi[1] & 0x20) { | 
 | 10313 |     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */ | 
 | 10314 |     for(i=1; i<chi[0] && !(chi[i] &0x80); i++); | 
 | 10315 |     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe; | 
 | 10316 |     if((chi[1] |0xc8)!=0xe9) return 0xfe; | 
 | 10317 |     if(chi[1] &0x08) excl = 0x40; | 
 | 10318 |  | 
 | 10319 |         /* int. id present */ | 
 | 10320 |     if(chi[1] &0x40) { | 
 | 10321 |       p=i+1; | 
 | 10322 |       for(i=p; i<chi[0] && !(chi[i] &0x80); i++); | 
 | 10323 |       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe; | 
 | 10324 |     } | 
 | 10325 |  | 
 | 10326 |         /* coding standard, Number/Map, Channel Type */ | 
 | 10327 |     p=i+1; | 
 | 10328 |     for(i=p; i<chi[0] && !(chi[i] &0x80); i++); | 
 | 10329 |     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe; | 
 | 10330 |     if((chi[p]|0xd0)!=0xd3) return 0xfe; | 
 | 10331 |  | 
 | 10332 |         /* Number/Map */ | 
 | 10333 |     if(chi[p] &0x10) { | 
 | 10334 |  | 
 | 10335 |         /* map */ | 
 | 10336 |       if((chi[0]-p)==4) ofs = 0; | 
 | 10337 |       else if((chi[0]-p)==3) ofs = 1; | 
 | 10338 |       else return 0xfe; | 
 | 10339 |       ch = 0; | 
 | 10340 |       map = 0; | 
 | 10341 |       for(i=0; i<4 && p<chi[0]; i++) { | 
 | 10342 |         p++; | 
 | 10343 |         ch += 8; | 
 | 10344 |         map <<= 8; | 
 | 10345 |         if(chi[p]) { | 
 | 10346 |           for (ch=0; !(chi[p] & (1 << ch)); ch++); | 
 | 10347 |           map |= chi[p]; | 
 | 10348 |         } | 
 | 10349 |       } | 
 | 10350 |       ch += ofs; | 
 | 10351 |       map <<= ofs; | 
 | 10352 |     } | 
 | 10353 |     else { | 
 | 10354 |  | 
 | 10355 |         /* number */ | 
 | 10356 |       p=i+1; | 
 | 10357 |       ch = chi[p] &0x3f; | 
 | 10358 |       if(pchannelmap) { | 
 | 10359 |         if((byte)(chi[0]-p)>30) return 0xfe; | 
 | 10360 |         map = 0; | 
 | 10361 |         for(i=p; i<=chi[0]; i++) { | 
 | 10362 |           if ((chi[i] &0x7f) > 31) return 0xfe; | 
 | 10363 |           map |= (1L << (chi[i] &0x7f)); | 
 | 10364 |         } | 
 | 10365 |       } | 
 | 10366 |       else { | 
 | 10367 |         if(p!=chi[0]) return 0xfe; | 
 | 10368 |         if (ch > 31) return 0xfe; | 
 | 10369 |         map = (1L << ch); | 
 | 10370 |       } | 
 | 10371 |       if(chi[p] &0x40) return 0xfe; | 
 | 10372 |     } | 
 | 10373 |     if (pchannelmap) *pchannelmap = map; | 
 | 10374 |     else if (map != ((dword)(1L << ch))) return 0xfe; | 
 | 10375 |     return (byte)(excl | ch); | 
 | 10376 |   } | 
 | 10377 |   else {  /* not PRI */ | 
 | 10378 |     for(i=1; i<chi[0] && !(chi[i] &0x80); i++); | 
 | 10379 |     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe; | 
 | 10380 |     if(chi[1] &0x08) excl = 0x40; | 
 | 10381 |  | 
 | 10382 |     switch(chi[1] |0x98) { | 
 | 10383 |     case 0x98: return 0; | 
 | 10384 |     case 0x99: | 
 | 10385 |       if (pchannelmap) *pchannelmap = 2; | 
 | 10386 |       return excl |1; | 
 | 10387 |     case 0x9a: | 
 | 10388 |       if (pchannelmap) *pchannelmap = 4; | 
 | 10389 |       return excl |2; | 
 | 10390 |     case 0x9b: return 0xff; | 
 | 10391 |     case 0x9c: return 0xfd; /* d-ch */ | 
 | 10392 |     default: return 0xfe; | 
 | 10393 |     } | 
 | 10394 |   } | 
 | 10395 | } | 
 | 10396 |  | 
 | 10397 |  | 
 | 10398 | static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id) | 
 | 10399 | { | 
 | 10400 |   DIVA_CAPI_ADAPTER   *a; | 
 | 10401 |   PLCI   *splci; | 
 | 10402 |   byte old_id; | 
 | 10403 |  | 
 | 10404 |   a = plci->adapter; | 
 | 10405 |   old_id = plci->li_bchannel_id; | 
 | 10406 |   if (a->li_pri) | 
 | 10407 |   { | 
 | 10408 |     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | 
 | 10409 |       li_config_table[a->li_base + (old_id - 1)].plci = NULL; | 
 | 10410 |     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1; | 
 | 10411 |     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | 
 | 10412 |       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | 
 | 10413 |   } | 
 | 10414 |   else | 
 | 10415 |   { | 
 | 10416 |     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2)) | 
 | 10417 |     { | 
 | 10418 |       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | 
 | 10419 |         li_config_table[a->li_base + (old_id - 1)].plci = NULL; | 
 | 10420 |       plci->li_bchannel_id = bchannel_id & 0x03; | 
 | 10421 |       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | 
 | 10422 |       { | 
 | 10423 |         splci = a->AdvSignalPLCI; | 
 | 10424 |         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL) | 
 | 10425 |         { | 
 | 10426 |           if ((splci->li_bchannel_id != 0) | 
 | 10427 |            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci)) | 
 | 10428 |           { | 
 | 10429 |             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL; | 
 | 10430 |           } | 
 | 10431 |           splci->li_bchannel_id = 3 - plci->li_bchannel_id; | 
 | 10432 |           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci; | 
 | 10433 |           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d", | 
 | 10434 |             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)), | 
 | 10435 |             (char   *)(FILE_), __LINE__, splci->li_bchannel_id)); | 
 | 10436 |         } | 
 | 10437 |       } | 
 | 10438 |       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | 
 | 10439 |         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | 
 | 10440 |     } | 
 | 10441 |   } | 
 | 10442 |   if ((old_id == 0) && (plci->li_bchannel_id != 0) | 
 | 10443 |    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 10444 |   { | 
 | 10445 |     mixer_clear_config (plci); | 
 | 10446 |   } | 
 | 10447 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d", | 
 | 10448 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 10449 |     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id)); | 
 | 10450 | } | 
 | 10451 |  | 
 | 10452 |  | 
 | 10453 | static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi) | 
 | 10454 | { | 
 | 10455 |   DIVA_CAPI_ADAPTER   *a; | 
 | 10456 |   PLCI   *splci; | 
 | 10457 |   byte ch, old_id; | 
 | 10458 |  | 
 | 10459 |   a = plci->adapter; | 
 | 10460 |   old_id = plci->li_bchannel_id; | 
 | 10461 |   ch = chi_to_channel (chi, NULL); | 
 | 10462 |   if (!(ch & 0x80)) | 
 | 10463 |   { | 
 | 10464 |     if (a->li_pri) | 
 | 10465 |     { | 
 | 10466 |       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | 
 | 10467 |         li_config_table[a->li_base + (old_id - 1)].plci = NULL; | 
 | 10468 |       plci->li_bchannel_id = (ch & 0x1f) + 1; | 
 | 10469 |       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | 
 | 10470 |         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | 
 | 10471 |     } | 
 | 10472 |     else | 
 | 10473 |     { | 
 | 10474 |       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2)) | 
 | 10475 |       { | 
 | 10476 |         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | 
 | 10477 |           li_config_table[a->li_base + (old_id - 1)].plci = NULL; | 
 | 10478 |         plci->li_bchannel_id = ch & 0x1f; | 
 | 10479 |         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | 
 | 10480 |         { | 
 | 10481 |           splci = a->AdvSignalPLCI; | 
 | 10482 |           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL) | 
 | 10483 |           { | 
 | 10484 |             if ((splci->li_bchannel_id != 0) | 
 | 10485 |              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci)) | 
 | 10486 |             { | 
 | 10487 |               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL; | 
 | 10488 |             } | 
 | 10489 |             splci->li_bchannel_id = 3 - plci->li_bchannel_id; | 
 | 10490 |             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci; | 
 | 10491 |             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d", | 
 | 10492 |               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)), | 
 | 10493 |               (char   *)(FILE_), __LINE__, splci->li_bchannel_id)); | 
 | 10494 |           } | 
 | 10495 |         } | 
 | 10496 |         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | 
 | 10497 |           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | 
 | 10498 |       } | 
 | 10499 |     } | 
 | 10500 |   } | 
 | 10501 |   if ((old_id == 0) && (plci->li_bchannel_id != 0) | 
 | 10502 |    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 10503 |   { | 
 | 10504 |     mixer_clear_config (plci); | 
 | 10505 |   } | 
 | 10506 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d", | 
 | 10507 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 10508 |     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id)); | 
 | 10509 | } | 
 | 10510 |  | 
 | 10511 |  | 
 | 10512 | #define MIXER_MAX_DUMP_CHANNELS 34 | 
 | 10513 |  | 
 | 10514 | static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a) | 
 | 10515 | { | 
 | 10516 | static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; | 
 | 10517 |   word n, i, j; | 
 | 10518 |   char *p; | 
 | 10519 |     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4]; | 
 | 10520 |  | 
 | 10521 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs", | 
 | 10522 |     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__)); | 
 | 10523 |  | 
 | 10524 |   for (i = 0; i < li_total_channels; i++) | 
 | 10525 |   { | 
 | 10526 |     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET; | 
 | 10527 |     if (li_config_table[i].chflags != 0) | 
 | 10528 |       li_config_table[i].channel |= LI_CHANNEL_INVOLVED; | 
 | 10529 |     else | 
 | 10530 |     { | 
 | 10531 |       for (j = 0; j < li_total_channels; j++) | 
 | 10532 |       { | 
 | 10533 |         if (((li_config_table[i].flag_table[j]) != 0) | 
 | 10534 |          || ((li_config_table[j].flag_table[i]) != 0)) | 
 | 10535 |         { | 
 | 10536 |           li_config_table[i].channel |= LI_CHANNEL_INVOLVED; | 
 | 10537 |         } | 
 | 10538 |         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0) | 
 | 10539 |          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0)) | 
 | 10540 |         { | 
 | 10541 |           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE; | 
 | 10542 |         } | 
 | 10543 |       } | 
 | 10544 |     } | 
 | 10545 |   } | 
 | 10546 |   for (i = 0; i < li_total_channels; i++) | 
 | 10547 |   { | 
 | 10548 |     for (j = 0; j < li_total_channels; j++) | 
 | 10549 |     { | 
 | 10550 |       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC); | 
 | 10551 |       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) | 
 | 10552 |         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH; | 
 | 10553 |     } | 
 | 10554 |   } | 
 | 10555 |   for (n = 0; n < li_total_channels; n++) | 
 | 10556 |   { | 
 | 10557 |     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE) | 
 | 10558 |     { | 
 | 10559 |       for (i = 0; i < li_total_channels; i++) | 
 | 10560 |       { | 
 | 10561 |         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE) | 
 | 10562 |         { | 
 | 10563 |           for (j = 0; j < li_total_channels; j++) | 
 | 10564 |           { | 
 | 10565 |             li_config_table[i].coef_table[j] |= | 
 | 10566 |               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j]; | 
 | 10567 |           } | 
 | 10568 |         } | 
 | 10569 |       } | 
 | 10570 |     } | 
 | 10571 |   } | 
 | 10572 |   for (i = 0; i < li_total_channels; i++) | 
 | 10573 |   { | 
 | 10574 |     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | 
 | 10575 |     { | 
 | 10576 |       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH; | 
 | 10577 |       for (j = 0; j < li_total_channels; j++) | 
 | 10578 |       { | 
 | 10579 |         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH) | 
 | 10580 |           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE; | 
 | 10581 |       } | 
 | 10582 |       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE) | 
 | 10583 |         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH; | 
 | 10584 |     } | 
 | 10585 |   } | 
 | 10586 |   for (i = 0; i < li_total_channels; i++) | 
 | 10587 |   { | 
 | 10588 |     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | 
 | 10589 |     { | 
 | 10590 |       for (j = 0; j < li_total_channels; j++) | 
 | 10591 |       { | 
 | 10592 |         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | 
 | 10593 |           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH; | 
 | 10594 |         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR) | 
 | 10595 |           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC; | 
 | 10596 |         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX) | 
 | 10597 |           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH; | 
 | 10598 |         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT) | 
 | 10599 |           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC; | 
 | 10600 |       } | 
 | 10601 |       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR) | 
 | 10602 |       { | 
 | 10603 |         for (j = 0; j < li_total_channels; j++) | 
 | 10604 |         { | 
 | 10605 |           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | 
 | 10606 |           { | 
 | 10607 |             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC; | 
 | 10608 |             if (li_config_table[j].chflags & LI_CHFLAG_MIX) | 
 | 10609 |               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC; | 
 | 10610 |           } | 
 | 10611 |         } | 
 | 10612 |       } | 
 | 10613 |       if (li_config_table[i].chflags & LI_CHFLAG_MIX) | 
 | 10614 |       { | 
 | 10615 |         for (j = 0; j < li_total_channels; j++) | 
 | 10616 |         { | 
 | 10617 |           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT) | 
 | 10618 |             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH; | 
 | 10619 |         } | 
 | 10620 |       } | 
 | 10621 |       if (li_config_table[i].chflags & LI_CHFLAG_LOOP) | 
 | 10622 |       { | 
 | 10623 |         for (j = 0; j < li_total_channels; j++) | 
 | 10624 |         { | 
 | 10625 |           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | 
 | 10626 |           { | 
 | 10627 |             for (n = 0; n < li_total_channels; n++) | 
 | 10628 |             { | 
 | 10629 |               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT) | 
 | 10630 |               { | 
 | 10631 |                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH; | 
 | 10632 |                 if (li_config_table[j].chflags & LI_CHFLAG_MIX) | 
 | 10633 |                 { | 
 | 10634 |                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH; | 
 | 10635 |                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR) | 
 | 10636 |                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC; | 
 | 10637 |                 } | 
 | 10638 |                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR) | 
 | 10639 |                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC; | 
 | 10640 |               } | 
 | 10641 |             } | 
 | 10642 |           } | 
 | 10643 |         } | 
 | 10644 |       } | 
 | 10645 |     } | 
 | 10646 |   } | 
 | 10647 |   for (i = 0; i < li_total_channels; i++) | 
 | 10648 |   { | 
 | 10649 |     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | 
 | 10650 |     { | 
 | 10651 |       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP)) | 
 | 10652 |         li_config_table[i].channel |= LI_CHANNEL_ACTIVE; | 
 | 10653 |       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR) | 
 | 10654 |         li_config_table[i].channel |= LI_CHANNEL_RX_DATA; | 
 | 10655 |       if (li_config_table[i].chflags & LI_CHFLAG_MIX) | 
 | 10656 |         li_config_table[i].channel |= LI_CHANNEL_TX_DATA; | 
 | 10657 |       for (j = 0; j < li_total_channels; j++) | 
 | 10658 |       { | 
 | 10659 |         if ((li_config_table[i].flag_table[j] & | 
 | 10660 |           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR)) | 
 | 10661 |          || (li_config_table[j].flag_table[i] & | 
 | 10662 |           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))) | 
 | 10663 |         { | 
 | 10664 |           li_config_table[i].channel |= LI_CHANNEL_ACTIVE; | 
 | 10665 |         } | 
 | 10666 |         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR)) | 
 | 10667 |           li_config_table[i].channel |= LI_CHANNEL_RX_DATA; | 
 | 10668 |         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)) | 
 | 10669 |           li_config_table[i].channel |= LI_CHANNEL_TX_DATA; | 
 | 10670 |       } | 
 | 10671 |       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE)) | 
 | 10672 |       { | 
 | 10673 |         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC; | 
 | 10674 |         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA; | 
 | 10675 |       } | 
 | 10676 |     } | 
 | 10677 |   } | 
 | 10678 |   for (i = 0; i < li_total_channels; i++) | 
 | 10679 |   { | 
 | 10680 |     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | 
 | 10681 |     { | 
 | 10682 |       j = 0; | 
 | 10683 |       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)) | 
 | 10684 |         j++; | 
 | 10685 |       if (j < li_total_channels) | 
 | 10686 |       { | 
 | 10687 |         for (j = 0; j < li_total_channels; j++) | 
 | 10688 |         { | 
 | 10689 |           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH); | 
 | 10690 |           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT) | 
 | 10691 |             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH; | 
 | 10692 |         } | 
 | 10693 |       } | 
 | 10694 |     } | 
 | 10695 |   } | 
 | 10696 |   n = li_total_channels; | 
 | 10697 |   if (n > MIXER_MAX_DUMP_CHANNELS) | 
 | 10698 |     n = MIXER_MAX_DUMP_CHANNELS; | 
 | 10699 |   p = hex_line; | 
 | 10700 |   for (j = 0; j < n; j++) | 
 | 10701 |   { | 
 | 10702 |     if ((j & 0x7) == 0) | 
 | 10703 |       *(p++) = ' '; | 
 | 10704 |     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4]; | 
 | 10705 |     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf]; | 
 | 10706 |   } | 
 | 10707 |   *p = '\0'; | 
 | 10708 |   dbug (1, dprintf ("[%06lx] CURRENT %s", | 
 | 10709 |     (dword)(UnMapController (a->Id)), (char   *) hex_line)); | 
 | 10710 |   p = hex_line; | 
 | 10711 |   for (j = 0; j < n; j++) | 
 | 10712 |   { | 
 | 10713 |     if ((j & 0x7) == 0) | 
 | 10714 |       *(p++) = ' '; | 
 | 10715 |     *(p++) = hex_digit_table[li_config_table[j].channel >> 4]; | 
 | 10716 |     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf]; | 
 | 10717 |   } | 
 | 10718 |   *p = '\0'; | 
 | 10719 |   dbug (1, dprintf ("[%06lx] CHANNEL %s", | 
 | 10720 |     (dword)(UnMapController (a->Id)), (char   *) hex_line)); | 
 | 10721 |   p = hex_line; | 
 | 10722 |   for (j = 0; j < n; j++) | 
 | 10723 |   { | 
 | 10724 |     if ((j & 0x7) == 0) | 
 | 10725 |       *(p++) = ' '; | 
 | 10726 |     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4]; | 
 | 10727 |     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf]; | 
 | 10728 |   } | 
 | 10729 |   *p = '\0'; | 
 | 10730 |   dbug (1, dprintf ("[%06lx] CHFLAG  %s", | 
 | 10731 |     (dword)(UnMapController (a->Id)), (char   *) hex_line)); | 
 | 10732 |   for (i = 0; i < n; i++) | 
 | 10733 |   { | 
 | 10734 |     p = hex_line; | 
 | 10735 |     for (j = 0; j < n; j++) | 
 | 10736 |     { | 
 | 10737 |       if ((j & 0x7) == 0) | 
 | 10738 |         *(p++) = ' '; | 
 | 10739 |       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4]; | 
 | 10740 |       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf]; | 
 | 10741 |     } | 
 | 10742 |     *p = '\0'; | 
 | 10743 |     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s", | 
 | 10744 |       (dword)(UnMapController (a->Id)), i, (char   *) hex_line)); | 
 | 10745 |   } | 
 | 10746 |   for (i = 0; i < n; i++) | 
 | 10747 |   { | 
 | 10748 |     p = hex_line; | 
 | 10749 |     for (j = 0; j < n; j++) | 
 | 10750 |     { | 
 | 10751 |       if ((j & 0x7) == 0) | 
 | 10752 |         *(p++) = ' '; | 
 | 10753 |       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4]; | 
 | 10754 |       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf]; | 
 | 10755 |     } | 
 | 10756 |     *p = '\0'; | 
 | 10757 |     dbug (1, dprintf ("[%06lx] COEF[%02x]%s", | 
 | 10758 |       (dword)(UnMapController (a->Id)), i, (char   *) hex_line)); | 
 | 10759 |   } | 
 | 10760 | } | 
 | 10761 |  | 
 | 10762 |  | 
 | 10763 | static struct | 
 | 10764 | { | 
 | 10765 |   byte mask; | 
 | 10766 |   byte line_flags; | 
 | 10767 | } mixer_write_prog_pri[] = | 
 | 10768 | { | 
 | 10769 |   { LI_COEF_CH_CH, 0 }, | 
 | 10770 |   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG }, | 
 | 10771 |   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG }, | 
 | 10772 |   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG } | 
 | 10773 | }; | 
 | 10774 |  | 
 | 10775 | static struct | 
 | 10776 | { | 
 | 10777 |   byte from_ch; | 
 | 10778 |   byte to_ch; | 
 | 10779 |   byte mask; | 
 | 10780 |   byte xconnect_override; | 
 | 10781 | } mixer_write_prog_bri[] = | 
 | 10782 | { | 
 | 10783 |   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */ | 
 | 10784 |   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */ | 
 | 10785 |   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */ | 
 | 10786 |   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */ | 
 | 10787 |   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */ | 
 | 10788 |   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */ | 
 | 10789 |   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */ | 
 | 10790 |   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */ | 
 | 10791 |   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */ | 
 | 10792 |   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */ | 
 | 10793 |   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */ | 
 | 10794 |   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */ | 
 | 10795 |   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */ | 
 | 10796 |   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */ | 
 | 10797 |   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */ | 
 | 10798 |   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */ | 
 | 10799 |   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */ | 
 | 10800 |   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */ | 
 | 10801 |   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */ | 
 | 10802 |   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */ | 
 | 10803 |   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */ | 
 | 10804 |   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */ | 
 | 10805 |   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */ | 
 | 10806 |   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */ | 
 | 10807 |   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */ | 
 | 10808 |   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */ | 
 | 10809 |   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */ | 
 | 10810 |   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */ | 
 | 10811 |   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */ | 
 | 10812 |   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */ | 
 | 10813 |   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */ | 
 | 10814 |   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */ | 
 | 10815 |   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */ | 
 | 10816 |   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */ | 
 | 10817 |   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */ | 
 | 10818 |   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */ | 
 | 10819 | }; | 
 | 10820 |  | 
 | 10821 | static byte mixer_swapped_index_bri[] = | 
 | 10822 | { | 
 | 10823 |   18,  /* B      to B      */ | 
 | 10824 |   19,  /* Alt B  to B      */ | 
 | 10825 |   20,  /* PC     to B      */ | 
 | 10826 |   21,  /* Alt PC to B      */ | 
 | 10827 |   22,  /* IC     to B      */ | 
 | 10828 |   23,  /* Alt IC to B      */ | 
 | 10829 |   24,  /* B      to PC     */ | 
 | 10830 |   25,  /* Alt B  to PC     */ | 
 | 10831 |   26,  /* PC     to PC     */ | 
 | 10832 |   27,  /* Alt PC to PC     */ | 
 | 10833 |   28,  /* IC     to PC     */ | 
 | 10834 |   29,  /* Alt IC to PC     */ | 
 | 10835 |   30,  /* B      to IC     */ | 
 | 10836 |   31,  /* Alt B  to IC     */ | 
 | 10837 |   32,  /* PC     to IC     */ | 
 | 10838 |   33,  /* Alt PC to IC     */ | 
 | 10839 |   34,  /* IC     to IC     */ | 
 | 10840 |   35,  /* Alt IC to IC     */ | 
 | 10841 |   0,   /* Alt B  to Alt B  */ | 
 | 10842 |   1,   /* B      to Alt B  */ | 
 | 10843 |   2,   /* Alt PC to Alt B  */ | 
 | 10844 |   3,   /* PC     to Alt B  */ | 
 | 10845 |   4,   /* Alt IC to Alt B  */ | 
 | 10846 |   5,   /* IC     to Alt B  */ | 
 | 10847 |   6,   /* Alt B  to Alt PC */ | 
 | 10848 |   7,   /* B      to Alt PC */ | 
 | 10849 |   8,   /* Alt PC to Alt PC */ | 
 | 10850 |   9,   /* PC     to Alt PC */ | 
 | 10851 |   10,  /* Alt IC to Alt PC */ | 
 | 10852 |   11,  /* IC     to Alt PC */ | 
 | 10853 |   12,  /* Alt B  to Alt IC */ | 
 | 10854 |   13,  /* B      to Alt IC */ | 
 | 10855 |   14,  /* Alt PC to Alt IC */ | 
 | 10856 |   15,  /* PC     to Alt IC */ | 
 | 10857 |   16,  /* Alt IC to Alt IC */ | 
 | 10858 |   17   /* IC     to Alt IC */ | 
 | 10859 | }; | 
 | 10860 |  | 
 | 10861 | static struct | 
 | 10862 | { | 
 | 10863 |   byte mask; | 
 | 10864 |   byte from_pc; | 
 | 10865 |   byte to_pc; | 
 | 10866 | } xconnect_write_prog[] = | 
 | 10867 | { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 10868 |   { LI_COEF_CH_CH, false, false }, | 
 | 10869 |   { LI_COEF_CH_PC, false, true }, | 
 | 10870 |   { LI_COEF_PC_CH, true, false }, | 
 | 10871 |   { LI_COEF_PC_PC, true, true } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10872 | }; | 
 | 10873 |  | 
 | 10874 |  | 
 | 10875 | static void xconnect_query_addresses (PLCI   *plci) | 
 | 10876 | { | 
 | 10877 |   DIVA_CAPI_ADAPTER   *a; | 
 | 10878 |   word w, ch; | 
 | 10879 |   byte   *p; | 
 | 10880 |  | 
 | 10881 |   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses", | 
 | 10882 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 10883 |     (char   *)(FILE_), __LINE__)); | 
 | 10884 |  | 
 | 10885 |   a = plci->adapter; | 
 | 10886 |   if (a->li_pri && ((plci->li_bchannel_id == 0) | 
 | 10887 |    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))) | 
 | 10888 |   { | 
 | 10889 |     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out", | 
 | 10890 |       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 10891 |       (char   *)(FILE_), __LINE__)); | 
 | 10892 |     return; | 
 | 10893 |   } | 
 | 10894 |   p = plci->internal_req_buffer; | 
 | 10895 |   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0; | 
 | 10896 |   *(p++) = UDATA_REQUEST_XCONNECT_FROM; | 
 | 10897 |   w = ch; | 
 | 10898 |   *(p++) = (byte) w; | 
 | 10899 |   *(p++) = (byte)(w >> 8); | 
 | 10900 |   w = ch | XCONNECT_CHANNEL_PORT_PC; | 
 | 10901 |   *(p++) = (byte) w; | 
 | 10902 |   *(p++) = (byte)(w >> 8); | 
 | 10903 |   plci->NData[0].P = plci->internal_req_buffer; | 
 | 10904 |   plci->NData[0].PLength = p - plci->internal_req_buffer; | 
 | 10905 |   plci->NL.X = plci->NData; | 
 | 10906 |   plci->NL.ReqCh = 0; | 
 | 10907 |   plci->NL.Req = plci->nl_req = (byte) N_UDATA; | 
 | 10908 |   plci->adapter->request (&plci->NL); | 
 | 10909 | } | 
 | 10910 |  | 
 | 10911 |  | 
 | 10912 | static void xconnect_write_coefs (PLCI   *plci, word internal_command) | 
 | 10913 | { | 
 | 10914 |  | 
 | 10915 |   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x", | 
 | 10916 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 10917 |     (char   *)(FILE_), __LINE__, internal_command)); | 
 | 10918 |  | 
 | 10919 |   plci->li_write_command = internal_command; | 
 | 10920 |   plci->li_write_channel = 0; | 
 | 10921 | } | 
 | 10922 |  | 
 | 10923 |  | 
 | 10924 | static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc) | 
 | 10925 | { | 
 | 10926 |   DIVA_CAPI_ADAPTER   *a; | 
 | 10927 |   word w, n, i, j, r, s, to_ch; | 
 | 10928 |   dword d; | 
 | 10929 |   byte   *p; | 
 | 10930 |   struct xconnect_transfer_address_s   *transfer_address; | 
 | 10931 |   byte ch_map[MIXER_CHANNELS_BRI]; | 
 | 10932 |  | 
 | 10933 |   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d", | 
 | 10934 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel)); | 
 | 10935 |  | 
 | 10936 |   a = plci->adapter; | 
 | 10937 |   if ((plci->li_bchannel_id == 0) | 
 | 10938 |    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)) | 
 | 10939 |   { | 
 | 10940 |     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out", | 
 | 10941 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 10942 |     return (true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10943 |   } | 
 | 10944 |   i = a->li_base + (plci->li_bchannel_id - 1); | 
 | 10945 |   j = plci->li_write_channel; | 
 | 10946 |   p = plci->internal_req_buffer; | 
 | 10947 |   if (j != 0) | 
 | 10948 |   { | 
 | 10949 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 10950 |     { | 
 | 10951 |       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x", | 
 | 10952 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 10953 |       return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10954 |     } | 
 | 10955 |   } | 
 | 10956 |   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 10957 |   { | 
 | 10958 |     r = 0; | 
 | 10959 |     s = 0; | 
 | 10960 |     if (j < li_total_channels) | 
 | 10961 |     { | 
 | 10962 |       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET) | 
 | 10963 |       { | 
 | 10964 |         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ? | 
 | 10965 |             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) & | 
 | 10966 |           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ? | 
 | 10967 |             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH)); | 
 | 10968 |       } | 
 | 10969 |       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | 
 | 10970 |       while ((j < li_total_channels) | 
 | 10971 |         && ((r == 0) | 
 | 10972 |          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET)) | 
 | 10973 |          || (!li_config_table[j].adapter->li_pri | 
 | 10974 |           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI)) | 
 | 10975 |          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low) | 
 | 10976 |            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high)) | 
 | 10977 |           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT) | 
 | 10978 |            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT))) | 
 | 10979 |          || ((li_config_table[j].adapter->li_base != a->li_base) | 
 | 10980 |           && !(r & s & | 
 | 10981 |             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ? | 
 | 10982 |               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) & | 
 | 10983 |             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ? | 
 | 10984 |               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC)))))) | 
 | 10985 |       { | 
 | 10986 |         j++; | 
 | 10987 |         if (j < li_total_channels) | 
 | 10988 |           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | 
 | 10989 |       } | 
 | 10990 |     } | 
 | 10991 |     if (j < li_total_channels) | 
 | 10992 |     { | 
 | 10993 |       plci->internal_command = plci->li_write_command; | 
 | 10994 |       if (plci_nl_busy (plci)) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 10995 |         return (true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10996 |       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0; | 
 | 10997 |       *(p++) = UDATA_REQUEST_XCONNECT_TO; | 
 | 10998 |       do | 
 | 10999 |       { | 
 | 11000 |         if (li_config_table[j].adapter->li_base != a->li_base) | 
 | 11001 |         { | 
 | 11002 |           r &= s & | 
 | 11003 |             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ? | 
 | 11004 |               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) & | 
 | 11005 |             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ? | 
 | 11006 |               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC)); | 
 | 11007 |         } | 
 | 11008 |         n = 0; | 
 | 11009 |         do | 
 | 11010 |         { | 
 | 11011 |           if (r & xconnect_write_prog[n].mask) | 
 | 11012 |           { | 
 | 11013 |             if (xconnect_write_prog[n].from_pc) | 
 | 11014 |               transfer_address = &(li_config_table[j].send_pc); | 
 | 11015 |             else | 
 | 11016 |               transfer_address = &(li_config_table[j].send_b); | 
 | 11017 |             d = transfer_address->card_address.low; | 
 | 11018 |             *(p++) = (byte) d; | 
 | 11019 |             *(p++) = (byte)(d >> 8); | 
 | 11020 |             *(p++) = (byte)(d >> 16); | 
 | 11021 |             *(p++) = (byte)(d >> 24); | 
 | 11022 |             d = transfer_address->card_address.high; | 
 | 11023 |             *(p++) = (byte) d; | 
 | 11024 |             *(p++) = (byte)(d >> 8); | 
 | 11025 |             *(p++) = (byte)(d >> 16); | 
 | 11026 |             *(p++) = (byte)(d >> 24); | 
 | 11027 |             d = transfer_address->offset; | 
 | 11028 |             *(p++) = (byte) d; | 
 | 11029 |             *(p++) = (byte)(d >> 8); | 
 | 11030 |             *(p++) = (byte)(d >> 16); | 
 | 11031 |             *(p++) = (byte)(d >> 24); | 
 | 11032 |             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch; | 
 | 11033 |             *(p++) = (byte) w; | 
 | 11034 |             *(p++) = (byte)(w >> 8); | 
 | 11035 |             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 : | 
 | 11036 |               (li_config_table[i].adapter->u_law ? | 
 | 11037 |                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) : | 
 | 11038 |                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80)); | 
 | 11039 |             *(p++) = (byte) w; | 
 | 11040 |             *(p++) = (byte) 0; | 
 | 11041 |             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4; | 
 | 11042 |           } | 
 | 11043 |           n++; | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 11044 |         } while ((n < ARRAY_SIZE(xconnect_write_prog)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11045 |           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE)); | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 11046 |         if (n == ARRAY_SIZE(xconnect_write_prog)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11047 |         { | 
 | 11048 |           do | 
 | 11049 |           { | 
 | 11050 |             j++; | 
 | 11051 |             if (j < li_total_channels) | 
 | 11052 |               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | 
 | 11053 |           } while ((j < li_total_channels) | 
 | 11054 |             && ((r == 0) | 
 | 11055 |              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET)) | 
 | 11056 |              || (!li_config_table[j].adapter->li_pri | 
 | 11057 |               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI)) | 
 | 11058 |              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low) | 
 | 11059 |                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high)) | 
 | 11060 |               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT) | 
 | 11061 |                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT))) | 
 | 11062 |              || ((li_config_table[j].adapter->li_base != a->li_base) | 
 | 11063 |               && !(r & s & | 
 | 11064 |                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ? | 
 | 11065 |                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) & | 
 | 11066 |                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ? | 
 | 11067 |                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC)))))); | 
 | 11068 |         } | 
 | 11069 |       } while ((j < li_total_channels) | 
 | 11070 |         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE)); | 
 | 11071 |     } | 
 | 11072 |     else if (j == li_total_channels) | 
 | 11073 |     { | 
 | 11074 |       plci->internal_command = plci->li_write_command; | 
 | 11075 |       if (plci_nl_busy (plci)) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11076 |         return (true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11077 |       if (a->li_pri) | 
 | 11078 |       { | 
 | 11079 |         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC; | 
 | 11080 |         w = 0; | 
 | 11081 |         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | 
 | 11082 |           w |= MIXER_FEATURE_ENABLE_TX_DATA; | 
 | 11083 |         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | 
 | 11084 |           w |= MIXER_FEATURE_ENABLE_RX_DATA; | 
 | 11085 |         *(p++) = (byte) w; | 
 | 11086 |         *(p++) = (byte)(w >> 8); | 
 | 11087 |       } | 
 | 11088 |       else | 
 | 11089 |       { | 
 | 11090 |         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI; | 
 | 11091 |         w = 0; | 
 | 11092 |         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI) | 
 | 11093 |          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)) | 
 | 11094 |         { | 
 | 11095 |           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); | 
 | 11096 |         } | 
 | 11097 |         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | 
 | 11098 |           w |= MIXER_FEATURE_ENABLE_TX_DATA; | 
 | 11099 |         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | 
 | 11100 |           w |= MIXER_FEATURE_ENABLE_RX_DATA; | 
 | 11101 |         *(p++) = (byte) w; | 
 | 11102 |         *(p++) = (byte)(w >> 8); | 
 | 11103 |         for (j = 0; j < sizeof(ch_map); j += 2) | 
 | 11104 |         { | 
 | 11105 |           if (plci->li_bchannel_id == 2) | 
 | 11106 |           { | 
 | 11107 |             ch_map[j] = (byte)(j+1); | 
 | 11108 |             ch_map[j+1] = (byte) j; | 
 | 11109 |           } | 
 | 11110 |           else | 
 | 11111 |           { | 
 | 11112 |             ch_map[j] = (byte) j; | 
 | 11113 |             ch_map[j+1] = (byte)(j+1); | 
 | 11114 |           } | 
 | 11115 |         } | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 11116 |         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11117 |         { | 
 | 11118 |           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch]; | 
 | 11119 |           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch]; | 
 | 11120 |           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED) | 
 | 11121 |           { | 
 | 11122 |             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ? | 
 | 11123 |               mixer_write_prog_bri[n].xconnect_override : | 
 | 11124 |               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01); | 
 | 11125 |             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI)) | 
 | 11126 |             { | 
 | 11127 |               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | 
 | 11128 |               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4; | 
 | 11129 |             } | 
 | 11130 |           } | 
 | 11131 |           else | 
 | 11132 |           { | 
 | 11133 |             *p = 0x00; | 
 | 11134 |             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | 
 | 11135 |             { | 
 | 11136 |               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n]; | 
 | 11137 |               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length) | 
 | 11138 |                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w]; | 
 | 11139 |             } | 
 | 11140 |           } | 
 | 11141 |           p++; | 
 | 11142 |         } | 
 | 11143 |       } | 
 | 11144 |       j = li_total_channels + 1; | 
 | 11145 |     } | 
 | 11146 |   } | 
 | 11147 |   else | 
 | 11148 |   { | 
 | 11149 |     if (j <= li_total_channels) | 
 | 11150 |     { | 
 | 11151 |       plci->internal_command = plci->li_write_command; | 
 | 11152 |       if (plci_nl_busy (plci)) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11153 |         return (true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11154 |       if (j < a->li_base) | 
 | 11155 |         j = a->li_base; | 
 | 11156 |       if (a->li_pri) | 
 | 11157 |       { | 
 | 11158 |         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC; | 
 | 11159 |         w = 0; | 
 | 11160 |         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | 
 | 11161 |           w |= MIXER_FEATURE_ENABLE_TX_DATA; | 
 | 11162 |         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | 
 | 11163 |           w |= MIXER_FEATURE_ENABLE_RX_DATA; | 
 | 11164 |         *(p++) = (byte) w; | 
 | 11165 |         *(p++) = (byte)(w >> 8); | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 11166 |         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11167 |         { | 
 | 11168 |           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags); | 
 | 11169 |           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++) | 
 | 11170 |           { | 
 | 11171 |             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | 
 | 11172 |             if (w & mixer_write_prog_pri[n].mask) | 
 | 11173 |             { | 
 | 11174 |               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01; | 
 | 11175 |               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4; | 
 | 11176 |             } | 
 | 11177 |             else | 
 | 11178 |               *(p++) = 0x00; | 
 | 11179 |           } | 
 | 11180 |           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags); | 
 | 11181 |           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++) | 
 | 11182 |           { | 
 | 11183 |             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4)); | 
 | 11184 |             if (w & mixer_write_prog_pri[n].mask) | 
 | 11185 |             { | 
 | 11186 |               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01; | 
 | 11187 |               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4; | 
 | 11188 |             } | 
 | 11189 |             else | 
 | 11190 |               *(p++) = 0x00; | 
 | 11191 |           } | 
 | 11192 |         } | 
 | 11193 |       } | 
 | 11194 |       else | 
 | 11195 |       { | 
 | 11196 |         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI; | 
 | 11197 |         w = 0; | 
 | 11198 |         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI) | 
 | 11199 |          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)) | 
 | 11200 |         { | 
 | 11201 |           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); | 
 | 11202 |         } | 
 | 11203 |         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | 
 | 11204 |           w |= MIXER_FEATURE_ENABLE_TX_DATA; | 
 | 11205 |         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | 
 | 11206 |           w |= MIXER_FEATURE_ENABLE_RX_DATA; | 
 | 11207 |         *(p++) = (byte) w; | 
 | 11208 |         *(p++) = (byte)(w >> 8); | 
 | 11209 |         for (j = 0; j < sizeof(ch_map); j += 2) | 
 | 11210 |         { | 
 | 11211 |           if (plci->li_bchannel_id == 2) | 
 | 11212 |           { | 
 | 11213 |             ch_map[j] = (byte)(j+1); | 
 | 11214 |             ch_map[j+1] = (byte) j; | 
 | 11215 |           } | 
 | 11216 |           else | 
 | 11217 |           { | 
 | 11218 |             ch_map[j] = (byte) j; | 
 | 11219 |             ch_map[j+1] = (byte)(j+1); | 
 | 11220 |           } | 
 | 11221 |         } | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 11222 |         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11223 |         { | 
 | 11224 |           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch]; | 
 | 11225 |           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch]; | 
 | 11226 |           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED) | 
 | 11227 |           { | 
 | 11228 |             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01); | 
 | 11229 |             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | 
 | 11230 |             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4; | 
 | 11231 |           } | 
 | 11232 |           else | 
 | 11233 |           { | 
 | 11234 |             *p = 0x00; | 
 | 11235 |             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | 
 | 11236 |             { | 
 | 11237 |               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n]; | 
 | 11238 |               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length) | 
 | 11239 |                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w]; | 
 | 11240 |             } | 
 | 11241 |           } | 
 | 11242 |           p++; | 
 | 11243 |         } | 
 | 11244 |       } | 
 | 11245 |       j = li_total_channels + 1; | 
 | 11246 |     } | 
 | 11247 |   } | 
 | 11248 |   plci->li_write_channel = j; | 
 | 11249 |   if (p != plci->internal_req_buffer) | 
 | 11250 |   { | 
 | 11251 |     plci->NData[0].P = plci->internal_req_buffer; | 
 | 11252 |     plci->NData[0].PLength = p - plci->internal_req_buffer; | 
 | 11253 |     plci->NL.X = plci->NData; | 
 | 11254 |     plci->NL.ReqCh = 0; | 
 | 11255 |     plci->NL.Req = plci->nl_req = (byte) N_UDATA; | 
 | 11256 |     plci->adapter->request (&plci->NL); | 
 | 11257 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11258 |   return (true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11259 | } | 
 | 11260 |  | 
 | 11261 |  | 
 | 11262 | static void mixer_notify_update (PLCI   *plci, byte others) | 
 | 11263 | { | 
 | 11264 |   DIVA_CAPI_ADAPTER   *a; | 
 | 11265 |   word i, w; | 
 | 11266 |   PLCI   *notify_plci; | 
 | 11267 |     byte msg[sizeof(CAPI_MSG_HEADER) + 6]; | 
 | 11268 |  | 
 | 11269 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d", | 
 | 11270 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 11271 |     (char   *)(FILE_), __LINE__, others)); | 
 | 11272 |  | 
 | 11273 |   a = plci->adapter; | 
 | 11274 |   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED) | 
 | 11275 |   { | 
 | 11276 |     if (others) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11277 |       plci->li_notify_update = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11278 |     i = 0; | 
 | 11279 |     do | 
 | 11280 |     { | 
 | 11281 |       notify_plci = NULL; | 
 | 11282 |       if (others) | 
 | 11283 |       { | 
 | 11284 |         while ((i < li_total_channels) && (li_config_table[i].plci == NULL)) | 
 | 11285 |           i++; | 
 | 11286 |         if (i < li_total_channels) | 
 | 11287 |           notify_plci = li_config_table[i++].plci; | 
 | 11288 |       } | 
 | 11289 |       else | 
 | 11290 |       { | 
 | 11291 |         if ((plci->li_bchannel_id != 0) | 
 | 11292 |          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 11293 |         { | 
 | 11294 |           notify_plci = plci; | 
 | 11295 |         } | 
 | 11296 |       } | 
 | 11297 |       if ((notify_plci != NULL) | 
 | 11298 |        && !notify_plci->li_notify_update | 
 | 11299 |        && (notify_plci->appl != NULL) | 
 | 11300 |        && (notify_plci->State) | 
 | 11301 |        && notify_plci->NL.Id && !notify_plci->nl_remove_id) | 
 | 11302 |       { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11303 |         notify_plci->li_notify_update = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11304 |         ((CAPI_MSG *) msg)->header.length = 18; | 
 | 11305 |         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id; | 
 | 11306 |         ((CAPI_MSG *) msg)->header.command = _FACILITY_R; | 
 | 11307 |         ((CAPI_MSG *) msg)->header.number = 0; | 
 | 11308 |         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id; | 
 | 11309 |         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id; | 
 | 11310 |         ((CAPI_MSG *) msg)->header.ncci = 0; | 
 | 11311 |         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT; | 
 | 11312 |         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3; | 
 | 11313 |         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE); | 
 | 11314 |         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0; | 
 | 11315 |         w = api_put (notify_plci->appl, (CAPI_MSG *) msg); | 
 | 11316 |         if (w != _QUEUE_FULL) | 
 | 11317 |         { | 
 | 11318 |           if (w != 0) | 
 | 11319 |           { | 
 | 11320 |             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d", | 
 | 11321 |               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 11322 |               (char   *)(FILE_), __LINE__, | 
 | 11323 |               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w)); | 
 | 11324 |           } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11325 |           notify_plci->li_notify_update = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11326 |         } | 
 | 11327 |       } | 
 | 11328 |     } while (others && (notify_plci != NULL)); | 
 | 11329 |     if (others) | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11330 |       plci->li_notify_update = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11331 |   } | 
 | 11332 | } | 
 | 11333 |  | 
 | 11334 |  | 
 | 11335 | static void mixer_clear_config (PLCI   *plci) | 
 | 11336 | { | 
 | 11337 |   DIVA_CAPI_ADAPTER   *a; | 
 | 11338 |   word i, j; | 
 | 11339 |  | 
 | 11340 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config", | 
 | 11341 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 11342 |     (char   *)(FILE_), __LINE__)); | 
 | 11343 |  | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 11344 |   plci->li_notify_update = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11345 |   plci->li_plci_b_write_pos = 0; | 
 | 11346 |   plci->li_plci_b_read_pos = 0; | 
 | 11347 |   plci->li_plci_b_req_pos = 0; | 
 | 11348 |   a = plci->adapter; | 
 | 11349 |   if ((plci->li_bchannel_id != 0) | 
 | 11350 |    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 11351 |   { | 
 | 11352 |     i = a->li_base + (plci->li_bchannel_id - 1); | 
 | 11353 |     li_config_table[i].curchnl = 0; | 
 | 11354 |     li_config_table[i].channel = 0; | 
 | 11355 |     li_config_table[i].chflags = 0; | 
 | 11356 |     for (j = 0; j < li_total_channels; j++) | 
 | 11357 |     { | 
 | 11358 |       li_config_table[j].flag_table[i] = 0; | 
 | 11359 |       li_config_table[i].flag_table[j] = 0; | 
 | 11360 |       li_config_table[i].coef_table[j] = 0; | 
 | 11361 |       li_config_table[j].coef_table[i] = 0; | 
 | 11362 |     } | 
 | 11363 |     if (!a->li_pri) | 
 | 11364 |     { | 
 | 11365 |       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET; | 
 | 11366 |       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | 
 | 11367 |       { | 
 | 11368 |         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | 
 | 11369 |         li_config_table[i].curchnl = 0; | 
 | 11370 |         li_config_table[i].channel = 0; | 
 | 11371 |         li_config_table[i].chflags = 0; | 
 | 11372 |         for (j = 0; j < li_total_channels; j++) | 
 | 11373 |         { | 
 | 11374 |           li_config_table[i].flag_table[j] = 0; | 
 | 11375 |           li_config_table[j].flag_table[i] = 0; | 
 | 11376 |           li_config_table[i].coef_table[j] = 0; | 
 | 11377 |           li_config_table[j].coef_table[i] = 0; | 
 | 11378 |         } | 
 | 11379 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | 
 | 11380 |         { | 
 | 11381 |           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | 
 | 11382 |           li_config_table[i].curchnl = 0; | 
 | 11383 |           li_config_table[i].channel = 0; | 
 | 11384 |           li_config_table[i].chflags = 0; | 
 | 11385 |           for (j = 0; j < li_total_channels; j++) | 
 | 11386 |           { | 
 | 11387 |             li_config_table[i].flag_table[j] = 0; | 
 | 11388 |             li_config_table[j].flag_table[i] = 0; | 
 | 11389 |             li_config_table[i].coef_table[j] = 0; | 
 | 11390 |             li_config_table[j].coef_table[i] = 0; | 
 | 11391 |           } | 
 | 11392 |         } | 
 | 11393 |       } | 
 | 11394 |     } | 
 | 11395 |   } | 
 | 11396 | } | 
 | 11397 |  | 
 | 11398 |  | 
 | 11399 | static void mixer_prepare_switch (dword Id, PLCI   *plci) | 
 | 11400 | { | 
 | 11401 |  | 
 | 11402 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch", | 
 | 11403 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11404 |  | 
 | 11405 |   do | 
 | 11406 |   { | 
 | 11407 |     mixer_indication_coefs_set (Id, plci); | 
 | 11408 |   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos); | 
 | 11409 | } | 
 | 11410 |  | 
 | 11411 |  | 
 | 11412 | static word mixer_save_config (dword Id, PLCI   *plci, byte Rc) | 
 | 11413 | { | 
 | 11414 |   DIVA_CAPI_ADAPTER   *a; | 
 | 11415 |   word i, j; | 
 | 11416 |  | 
 | 11417 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d", | 
 | 11418 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 11419 |  | 
 | 11420 |   a = plci->adapter; | 
 | 11421 |   if ((plci->li_bchannel_id != 0) | 
 | 11422 |    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 11423 |   { | 
 | 11424 |     i = a->li_base + (plci->li_bchannel_id - 1); | 
 | 11425 |     for (j = 0; j < li_total_channels; j++) | 
 | 11426 |     { | 
 | 11427 |       li_config_table[i].coef_table[j] &= 0xf; | 
 | 11428 |       li_config_table[j].coef_table[i] &= 0xf; | 
 | 11429 |     } | 
 | 11430 |     if (!a->li_pri) | 
 | 11431 |       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET; | 
 | 11432 |   } | 
 | 11433 |   return (GOOD); | 
 | 11434 | } | 
 | 11435 |  | 
 | 11436 |  | 
 | 11437 | static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc) | 
 | 11438 | { | 
 | 11439 |   DIVA_CAPI_ADAPTER   *a; | 
 | 11440 |   word Info; | 
 | 11441 |  | 
 | 11442 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d", | 
 | 11443 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 11444 |  | 
 | 11445 |   Info = GOOD; | 
 | 11446 |   a = plci->adapter; | 
 | 11447 |   if ((plci->B1_facilities & B1_FACILITY_MIXER) | 
 | 11448 |    && (plci->li_bchannel_id != 0) | 
 | 11449 |    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 11450 |   { | 
 | 11451 |     switch (plci->adjust_b_state) | 
 | 11452 |     { | 
 | 11453 |     case ADJUST_B_RESTORE_MIXER_1: | 
 | 11454 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 11455 |       { | 
 | 11456 |         plci->internal_command = plci->adjust_b_command; | 
 | 11457 |         if (plci_nl_busy (plci)) | 
 | 11458 |         { | 
 | 11459 |           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1; | 
 | 11460 |           break; | 
 | 11461 |         } | 
 | 11462 |         xconnect_query_addresses (plci); | 
 | 11463 |         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2; | 
 | 11464 |         break; | 
 | 11465 |       } | 
 | 11466 |       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5; | 
 | 11467 |       Rc = OK; | 
 | 11468 |     case ADJUST_B_RESTORE_MIXER_2: | 
 | 11469 |     case ADJUST_B_RESTORE_MIXER_3: | 
 | 11470 |     case ADJUST_B_RESTORE_MIXER_4: | 
 | 11471 |       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0)) | 
 | 11472 |       { | 
 | 11473 |         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x", | 
 | 11474 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 11475 |         Info = _WRONG_STATE; | 
 | 11476 |         break; | 
 | 11477 |       } | 
 | 11478 |       if (Rc == OK) | 
 | 11479 |       { | 
 | 11480 |         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2) | 
 | 11481 |           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3; | 
 | 11482 |         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4) | 
 | 11483 |           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5; | 
 | 11484 |       } | 
 | 11485 |       else if (Rc == 0) | 
 | 11486 |       { | 
 | 11487 |         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2) | 
 | 11488 |           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4; | 
 | 11489 |         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3) | 
 | 11490 |           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5; | 
 | 11491 |       } | 
 | 11492 |       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5) | 
 | 11493 |       { | 
 | 11494 |         plci->internal_command = plci->adjust_b_command; | 
 | 11495 |         break; | 
 | 11496 |       } | 
 | 11497 |     case ADJUST_B_RESTORE_MIXER_5: | 
 | 11498 |       xconnect_write_coefs (plci, plci->adjust_b_command); | 
 | 11499 |       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6; | 
 | 11500 |       Rc = OK; | 
 | 11501 |     case ADJUST_B_RESTORE_MIXER_6: | 
 | 11502 |       if (!xconnect_write_coefs_process (Id, plci, Rc)) | 
 | 11503 |       { | 
 | 11504 |         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed", | 
 | 11505 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11506 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 11507 |         break; | 
 | 11508 |       } | 
 | 11509 |       if (plci->internal_command) | 
 | 11510 |         break; | 
 | 11511 |       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7; | 
 | 11512 |     case ADJUST_B_RESTORE_MIXER_7: | 
 | 11513 |       break; | 
 | 11514 |     } | 
 | 11515 |   } | 
 | 11516 |   return (Info); | 
 | 11517 | } | 
 | 11518 |  | 
 | 11519 |  | 
 | 11520 | static void mixer_command (dword Id, PLCI   *plci, byte Rc) | 
 | 11521 | { | 
 | 11522 |   DIVA_CAPI_ADAPTER   *a; | 
 | 11523 |   word i, internal_command, Info; | 
 | 11524 |  | 
 | 11525 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x", | 
 | 11526 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command, | 
 | 11527 |     plci->li_cmd)); | 
 | 11528 |  | 
 | 11529 |   Info = GOOD; | 
 | 11530 |   a = plci->adapter; | 
 | 11531 |   internal_command = plci->internal_command; | 
 | 11532 |   plci->internal_command = 0; | 
 | 11533 |   switch (plci->li_cmd) | 
 | 11534 |   { | 
 | 11535 |   case LI_REQ_CONNECT: | 
 | 11536 |   case LI_REQ_DISCONNECT: | 
 | 11537 |   case LI_REQ_SILENT_UPDATE: | 
 | 11538 |     switch (internal_command) | 
 | 11539 |     { | 
 | 11540 |     default: | 
 | 11541 |       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED) | 
 | 11542 |       { | 
 | 11543 |         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | 
 | 11544 |           B1_FACILITY_MIXER), MIXER_COMMAND_1); | 
 | 11545 |       } | 
 | 11546 |     case MIXER_COMMAND_1: | 
 | 11547 |       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED) | 
 | 11548 |       { | 
 | 11549 |         if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 11550 |         { | 
 | 11551 |           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed", | 
 | 11552 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11553 |           Info = _FACILITY_NOT_SUPPORTED; | 
 | 11554 |           break; | 
 | 11555 |         } | 
 | 11556 |         if (plci->internal_command) | 
 | 11557 |           return; | 
 | 11558 |       } | 
 | 11559 |       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos; | 
 | 11560 |       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED) | 
 | 11561 |        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER) | 
 | 11562 |         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities & | 
 | 11563 |          ~B1_FACILITY_MIXER)) == plci->B1_resource))) | 
 | 11564 |       { | 
 | 11565 |         xconnect_write_coefs (plci, MIXER_COMMAND_2); | 
 | 11566 |       } | 
 | 11567 |       else | 
 | 11568 |       { | 
 | 11569 |         do | 
 | 11570 |         { | 
 | 11571 |           mixer_indication_coefs_set (Id, plci); | 
 | 11572 |         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos); | 
 | 11573 |       } | 
 | 11574 |     case MIXER_COMMAND_2: | 
 | 11575 |       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED) | 
 | 11576 |        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER) | 
 | 11577 |         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities & | 
 | 11578 |          ~B1_FACILITY_MIXER)) == plci->B1_resource))) | 
 | 11579 |       { | 
 | 11580 |         if (!xconnect_write_coefs_process (Id, plci, Rc)) | 
 | 11581 |         { | 
 | 11582 |           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed", | 
 | 11583 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11584 |           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos) | 
 | 11585 |           { | 
 | 11586 |             do | 
 | 11587 |             { | 
 | 11588 |               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ? | 
 | 11589 |                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1; | 
 | 11590 |               i = (plci->li_plci_b_write_pos == 0) ? | 
 | 11591 |                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1; | 
 | 11592 |             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos) | 
 | 11593 |               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)); | 
 | 11594 |           } | 
 | 11595 |           Info = _FACILITY_NOT_SUPPORTED; | 
 | 11596 |           break; | 
 | 11597 |         } | 
 | 11598 |         if (plci->internal_command) | 
 | 11599 |           return; | 
 | 11600 |       } | 
 | 11601 |       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED)) | 
 | 11602 |       { | 
 | 11603 |         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities & | 
 | 11604 |           ~B1_FACILITY_MIXER), MIXER_COMMAND_3); | 
 | 11605 |       } | 
 | 11606 |     case MIXER_COMMAND_3: | 
 | 11607 |       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED)) | 
 | 11608 |       { | 
 | 11609 |         if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 11610 |         { | 
 | 11611 |           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed", | 
 | 11612 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11613 |           Info = _FACILITY_NOT_SUPPORTED; | 
 | 11614 |           break; | 
 | 11615 |         } | 
 | 11616 |         if (plci->internal_command) | 
 | 11617 |           return; | 
 | 11618 |       } | 
 | 11619 |       break; | 
 | 11620 |     } | 
 | 11621 |     break; | 
 | 11622 |   } | 
 | 11623 |   if ((plci->li_bchannel_id == 0) | 
 | 11624 |    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)) | 
 | 11625 |   { | 
 | 11626 |     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d", | 
 | 11627 |       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id))); | 
 | 11628 |   } | 
 | 11629 |   else | 
 | 11630 |   { | 
 | 11631 |     i = a->li_base + (plci->li_bchannel_id - 1); | 
 | 11632 |     li_config_table[i].curchnl = plci->li_channel_bits; | 
 | 11633 |     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | 
 | 11634 |     { | 
 | 11635 |       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | 
 | 11636 |       li_config_table[i].curchnl = plci->li_channel_bits; | 
 | 11637 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | 
 | 11638 |       { | 
 | 11639 |         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | 
 | 11640 |         li_config_table[i].curchnl = plci->li_channel_bits; | 
 | 11641 |       } | 
 | 11642 |     } | 
 | 11643 |   } | 
 | 11644 | } | 
 | 11645 |  | 
 | 11646 |  | 
 | 11647 | static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, | 
 | 11648 |   dword plci_b_id, byte connect, dword li_flags) | 
 | 11649 | { | 
 | 11650 |   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s; | 
 | 11651 |   PLCI   *plci_b; | 
 | 11652 |   DIVA_CAPI_ADAPTER   *a_b; | 
 | 11653 |  | 
 | 11654 |   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]); | 
 | 11655 |   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]); | 
 | 11656 |   ch_a = a->li_base + (plci->li_bchannel_id - 1); | 
 | 11657 |   if (!a->li_pri && (plci->tel == ADV_VOICE) | 
 | 11658 |    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER)) | 
 | 11659 |   { | 
 | 11660 |     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE; | 
 | 11661 |     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | 
 | 11662 |       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v; | 
 | 11663 |   } | 
 | 11664 |   else | 
 | 11665 |   { | 
 | 11666 |     ch_a_v = ch_a; | 
 | 11667 |     ch_a_s = ch_a; | 
 | 11668 |   } | 
 | 11669 |   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1); | 
 | 11670 |   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE) | 
 | 11671 |    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER)) | 
 | 11672 |   { | 
 | 11673 |     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE; | 
 | 11674 |     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | 
 | 11675 |       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v; | 
 | 11676 |   } | 
 | 11677 |   else | 
 | 11678 |   { | 
 | 11679 |     ch_b_v = ch_b; | 
 | 11680 |     ch_b_s = ch_b; | 
 | 11681 |   } | 
 | 11682 |   if (connect) | 
 | 11683 |   { | 
 | 11684 |     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR; | 
 | 11685 |     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR; | 
 | 11686 |     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | 
 | 11687 |     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | 
 | 11688 |   } | 
 | 11689 |   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR; | 
 | 11690 |   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR; | 
 | 11691 |   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | 
 | 11692 |   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | 
 | 11693 |   if (ch_a_v == ch_b_v) | 
 | 11694 |   { | 
 | 11695 |     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE; | 
 | 11696 |     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE; | 
 | 11697 |   } | 
 | 11698 |   else | 
 | 11699 |   { | 
 | 11700 |     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE) | 
 | 11701 |     { | 
 | 11702 |       for (i = 0; i < li_total_channels; i++) | 
 | 11703 |       { | 
 | 11704 |         if (i != ch_a_v) | 
 | 11705 |           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE; | 
 | 11706 |       } | 
 | 11707 |     } | 
 | 11708 |     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE) | 
 | 11709 |     { | 
 | 11710 |       for (i = 0; i < li_total_channels; i++) | 
 | 11711 |       { | 
 | 11712 |         if (i != ch_a_s) | 
 | 11713 |           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE; | 
 | 11714 |       } | 
 | 11715 |     } | 
 | 11716 |     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE) | 
 | 11717 |     { | 
 | 11718 |       for (i = 0; i < li_total_channels; i++) | 
 | 11719 |       { | 
 | 11720 |         if (i != ch_a_v) | 
 | 11721 |           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE; | 
 | 11722 |       } | 
 | 11723 |     } | 
 | 11724 |     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE) | 
 | 11725 |     { | 
 | 11726 |       for (i = 0; i < li_total_channels; i++) | 
 | 11727 |       { | 
 | 11728 |         if (i != ch_a_s) | 
 | 11729 |           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE; | 
 | 11730 |       } | 
 | 11731 |     } | 
 | 11732 |   } | 
 | 11733 |   if (li_flags & LI_FLAG_CONFERENCE_A_B) | 
 | 11734 |   { | 
 | 11735 |     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | 
 | 11736 |     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | 
 | 11737 |     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | 
 | 11738 |     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | 
 | 11739 |   } | 
 | 11740 |   if (li_flags & LI_FLAG_CONFERENCE_B_A) | 
 | 11741 |   { | 
 | 11742 |     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | 
 | 11743 |     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | 
 | 11744 |     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | 
 | 11745 |     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | 
 | 11746 |   } | 
 | 11747 |   if (li_flags & LI_FLAG_MONITOR_A) | 
 | 11748 |   { | 
 | 11749 |     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR; | 
 | 11750 |     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR; | 
 | 11751 |   } | 
 | 11752 |   if (li_flags & LI_FLAG_MONITOR_B) | 
 | 11753 |   { | 
 | 11754 |     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR; | 
 | 11755 |     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR; | 
 | 11756 |   } | 
 | 11757 |   if (li_flags & LI_FLAG_ANNOUNCEMENT_A) | 
 | 11758 |   { | 
 | 11759 |     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | 
 | 11760 |     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | 
 | 11761 |   } | 
 | 11762 |   if (li_flags & LI_FLAG_ANNOUNCEMENT_B) | 
 | 11763 |   { | 
 | 11764 |     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | 
 | 11765 |     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | 
 | 11766 |   } | 
 | 11767 |   if (li_flags & LI_FLAG_MIX_A) | 
 | 11768 |   { | 
 | 11769 |     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX; | 
 | 11770 |     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX; | 
 | 11771 |   } | 
 | 11772 |   if (li_flags & LI_FLAG_MIX_B) | 
 | 11773 |   { | 
 | 11774 |     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX; | 
 | 11775 |     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX; | 
 | 11776 |   } | 
 | 11777 |   if (ch_a_v != ch_a_s) | 
 | 11778 |   { | 
 | 11779 |     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | 
 | 11780 |     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | 
 | 11781 |   } | 
 | 11782 |   if (ch_b_v != ch_b_s) | 
 | 11783 |   { | 
 | 11784 |     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | 
 | 11785 |     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | 
 | 11786 |   } | 
 | 11787 | } | 
 | 11788 |  | 
 | 11789 |  | 
 | 11790 | static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, | 
 | 11791 |   dword plci_b_id, byte connect, dword li_flags) | 
 | 11792 | { | 
 | 11793 |   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s; | 
 | 11794 |   PLCI   *plci_b; | 
 | 11795 |   DIVA_CAPI_ADAPTER   *a_b; | 
 | 11796 |  | 
 | 11797 |   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]); | 
 | 11798 |   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]); | 
 | 11799 |   ch_a = a->li_base + (plci->li_bchannel_id - 1); | 
 | 11800 |   if (!a->li_pri && (plci->tel == ADV_VOICE) | 
 | 11801 |    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER)) | 
 | 11802 |   { | 
 | 11803 |     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE; | 
 | 11804 |     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | 
 | 11805 |       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v; | 
 | 11806 |   } | 
 | 11807 |   else | 
 | 11808 |   { | 
 | 11809 |     ch_a_v = ch_a; | 
 | 11810 |     ch_a_s = ch_a; | 
 | 11811 |   } | 
 | 11812 |   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1); | 
 | 11813 |   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE) | 
 | 11814 |    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER)) | 
 | 11815 |   { | 
 | 11816 |     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE; | 
 | 11817 |     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | 
 | 11818 |       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v; | 
 | 11819 |   } | 
 | 11820 |   else | 
 | 11821 |   { | 
 | 11822 |     ch_b_v = ch_b; | 
 | 11823 |     ch_b_s = ch_b; | 
 | 11824 |   } | 
 | 11825 |   if (connect) | 
 | 11826 |   { | 
 | 11827 |     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR; | 
 | 11828 |     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR; | 
 | 11829 |     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX; | 
 | 11830 |     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX; | 
 | 11831 |     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT; | 
 | 11832 |     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP); | 
 | 11833 |   } | 
 | 11834 |   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11835 |   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11836 |   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11837 |   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11838 |   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11839 |   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11840 |   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11841 |   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | 
 | 11842 |   if (li_flags & LI2_FLAG_INTERCONNECT_A_B) | 
 | 11843 |   { | 
 | 11844 |     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT; | 
 | 11845 |     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT; | 
 | 11846 |     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT; | 
 | 11847 |     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT; | 
 | 11848 |   } | 
 | 11849 |   if (li_flags & LI2_FLAG_INTERCONNECT_B_A) | 
 | 11850 |   { | 
 | 11851 |     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | 
 | 11852 |     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | 
 | 11853 |     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | 
 | 11854 |     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | 
 | 11855 |   } | 
 | 11856 |   if (li_flags & LI2_FLAG_MONITOR_B) | 
 | 11857 |   { | 
 | 11858 |     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR; | 
 | 11859 |     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR; | 
 | 11860 |   } | 
 | 11861 |   if (li_flags & LI2_FLAG_MIX_B) | 
 | 11862 |   { | 
 | 11863 |     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX; | 
 | 11864 |     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX; | 
 | 11865 |   } | 
 | 11866 |   if (li_flags & LI2_FLAG_MONITOR_X) | 
 | 11867 |     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR; | 
 | 11868 |   if (li_flags & LI2_FLAG_MIX_X) | 
 | 11869 |     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX; | 
 | 11870 |   if (li_flags & LI2_FLAG_LOOP_B) | 
 | 11871 |   { | 
 | 11872 |     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | 
 | 11873 |     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | 
 | 11874 |     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | 
 | 11875 |     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | 
 | 11876 |   } | 
 | 11877 |   if (li_flags & LI2_FLAG_LOOP_PC) | 
 | 11878 |     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT; | 
 | 11879 |   if (li_flags & LI2_FLAG_LOOP_X) | 
 | 11880 |     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP; | 
 | 11881 |   if (li_flags & LI2_FLAG_PCCONNECT_A_B) | 
 | 11882 |     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT; | 
 | 11883 |   if (li_flags & LI2_FLAG_PCCONNECT_B_A) | 
 | 11884 |     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT; | 
 | 11885 |   if (ch_a_v != ch_a_s) | 
 | 11886 |   { | 
 | 11887 |     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | 
 | 11888 |     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | 
 | 11889 |   } | 
 | 11890 |   if (ch_b_v != ch_b_s) | 
 | 11891 |   { | 
 | 11892 |     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | 
 | 11893 |     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | 
 | 11894 |   } | 
 | 11895 | } | 
 | 11896 |  | 
 | 11897 |  | 
 | 11898 | static word li_check_main_plci (dword Id, PLCI   *plci) | 
 | 11899 | { | 
 | 11900 |   if (plci == NULL) | 
 | 11901 |   { | 
 | 11902 |     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | 
 | 11903 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11904 |     return (_WRONG_IDENTIFIER); | 
 | 11905 |   } | 
 | 11906 |   if (!plci->State | 
 | 11907 |    || !plci->NL.Id || plci->nl_remove_id | 
 | 11908 |    || (plci->li_bchannel_id == 0)) | 
 | 11909 |   { | 
 | 11910 |     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | 
 | 11911 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11912 |     return (_WRONG_STATE); | 
 | 11913 |   } | 
 | 11914 |   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci; | 
 | 11915 |   return (GOOD); | 
 | 11916 | } | 
 | 11917 |  | 
 | 11918 |  | 
 | 11919 | static PLCI   *li_check_plci_b (dword Id, PLCI   *plci, | 
 | 11920 |   dword plci_b_id, word plci_b_write_pos, byte   *p_result) | 
 | 11921 | { | 
 | 11922 |   byte ctlr_b; | 
 | 11923 |   PLCI   *plci_b; | 
 | 11924 |  | 
 | 11925 |   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | 
 | 11926 |     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2) | 
 | 11927 |   { | 
 | 11928 |     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | 
 | 11929 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11930 |     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); | 
 | 11931 |     return (NULL); | 
 | 11932 |   } | 
 | 11933 |   ctlr_b = 0; | 
 | 11934 |   if ((plci_b_id & 0x7f) != 0) | 
 | 11935 |   { | 
 | 11936 |     ctlr_b = MapController ((byte)(plci_b_id & 0x7f)); | 
 | 11937 |     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL))) | 
 | 11938 |       ctlr_b = 0; | 
 | 11939 |   } | 
 | 11940 |   if ((ctlr_b == 0) | 
 | 11941 |    || (((plci_b_id >> 8) & 0xff) == 0) | 
 | 11942 |    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci)) | 
 | 11943 |   { | 
 | 11944 |     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx", | 
 | 11945 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id)); | 
 | 11946 |     PUT_WORD (p_result, _WRONG_IDENTIFIER); | 
 | 11947 |     return (NULL); | 
 | 11948 |   } | 
 | 11949 |   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]); | 
 | 11950 |   if (!plci_b->State | 
 | 11951 |    || !plci_b->NL.Id || plci_b->nl_remove_id | 
 | 11952 |    || (plci_b->li_bchannel_id == 0)) | 
 | 11953 |   { | 
 | 11954 |     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx", | 
 | 11955 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id)); | 
 | 11956 |     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); | 
 | 11957 |     return (NULL); | 
 | 11958 |   } | 
 | 11959 |   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b; | 
 | 11960 |   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) != | 
 | 11961 |     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER)) | 
 | 11962 |    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 11963 |     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT))) | 
 | 11964 |   { | 
 | 11965 |     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx", | 
 | 11966 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id)); | 
 | 11967 |     PUT_WORD (p_result, _WRONG_IDENTIFIER); | 
 | 11968 |     return (NULL); | 
 | 11969 |   } | 
 | 11970 |   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource, | 
 | 11971 |     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER)) | 
 | 11972 |   { | 
 | 11973 |     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d", | 
 | 11974 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource)); | 
 | 11975 |     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); | 
 | 11976 |     return (NULL); | 
 | 11977 |   } | 
 | 11978 |   return (plci_b); | 
 | 11979 | } | 
 | 11980 |  | 
 | 11981 |  | 
 | 11982 | static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci, | 
 | 11983 |   dword plci_b_id, word plci_b_write_pos, byte   *p_result) | 
 | 11984 | { | 
 | 11985 |   byte ctlr_b; | 
 | 11986 |   PLCI   *plci_b; | 
 | 11987 |  | 
 | 11988 |   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | 
 | 11989 |     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2) | 
 | 11990 |   { | 
 | 11991 |     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | 
 | 11992 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 11993 |     PUT_WORD (p_result, _WRONG_STATE); | 
 | 11994 |     return (NULL); | 
 | 11995 |   } | 
 | 11996 |   ctlr_b = 0; | 
 | 11997 |   if ((plci_b_id & 0x7f) != 0) | 
 | 11998 |   { | 
 | 11999 |     ctlr_b = MapController ((byte)(plci_b_id & 0x7f)); | 
 | 12000 |     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL))) | 
 | 12001 |       ctlr_b = 0; | 
 | 12002 |   } | 
 | 12003 |   if ((ctlr_b == 0) | 
 | 12004 |    || (((plci_b_id >> 8) & 0xff) == 0) | 
 | 12005 |    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci)) | 
 | 12006 |   { | 
 | 12007 |     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx", | 
 | 12008 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id)); | 
 | 12009 |     PUT_WORD (p_result, _WRONG_IDENTIFIER); | 
 | 12010 |     return (NULL); | 
 | 12011 |   } | 
 | 12012 |   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]); | 
 | 12013 |   if (!plci_b->State | 
 | 12014 |    || !plci_b->NL.Id || plci_b->nl_remove_id | 
 | 12015 |    || (plci_b->li_bchannel_id == 0) | 
 | 12016 |    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b)) | 
 | 12017 |   { | 
 | 12018 |     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx", | 
 | 12019 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id)); | 
 | 12020 |     PUT_WORD (p_result, _WRONG_STATE); | 
 | 12021 |     return (NULL); | 
 | 12022 |   } | 
 | 12023 |   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) != | 
 | 12024 |     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER)) | 
 | 12025 |    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 12026 |     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT))) | 
 | 12027 |   { | 
 | 12028 |     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx", | 
 | 12029 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id)); | 
 | 12030 |     PUT_WORD (p_result, _WRONG_IDENTIFIER); | 
 | 12031 |     return (NULL); | 
 | 12032 |   } | 
 | 12033 |   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource, | 
 | 12034 |     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER)) | 
 | 12035 |   { | 
 | 12036 |     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d", | 
 | 12037 |       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource)); | 
 | 12038 |     PUT_WORD (p_result, _WRONG_STATE); | 
 | 12039 |     return (NULL); | 
 | 12040 |   } | 
 | 12041 |   return (plci_b); | 
 | 12042 | } | 
 | 12043 |  | 
 | 12044 |  | 
 | 12045 | static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg) | 
 | 12046 | { | 
 | 12047 |   word Info; | 
 | 12048 |   word i; | 
 | 12049 |   dword d, li_flags, plci_b_id; | 
 | 12050 |   PLCI   *plci_b; | 
 | 12051 |     API_PARSE li_parms[3]; | 
 | 12052 |     API_PARSE li_req_parms[3]; | 
 | 12053 |     API_PARSE li_participant_struct[2]; | 
 | 12054 |     API_PARSE li_participant_parms[3]; | 
 | 12055 |   word participant_parms_pos; | 
 | 12056 |   byte result_buffer[32]; | 
 | 12057 |   byte   *result; | 
 | 12058 |   word result_pos; | 
 | 12059 |   word plci_b_write_pos; | 
 | 12060 |  | 
 | 12061 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request", | 
 | 12062 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12063 |  | 
 | 12064 |   Info = GOOD; | 
 | 12065 |   result = result_buffer; | 
 | 12066 |   result_buffer[0] = 0; | 
 | 12067 |   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)) | 
 | 12068 |   { | 
 | 12069 |     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | 
 | 12070 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12071 |     Info = _FACILITY_NOT_SUPPORTED; | 
 | 12072 |   } | 
 | 12073 |   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms)) | 
 | 12074 |   { | 
 | 12075 |     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12076 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12077 |     Info = _WRONG_MESSAGE_FORMAT; | 
 | 12078 |   } | 
 | 12079 |   else | 
 | 12080 |   { | 
 | 12081 |     result_buffer[0] = 3; | 
 | 12082 |     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info)); | 
 | 12083 |     result_buffer[3] = 0; | 
 | 12084 |     switch (GET_WORD (li_parms[0].info)) | 
 | 12085 |     { | 
 | 12086 |     case LI_GET_SUPPORTED_SERVICES: | 
 | 12087 |       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC) | 
 | 12088 |       { | 
 | 12089 |         result_buffer[0] = 17; | 
 | 12090 |         result_buffer[3] = 14; | 
 | 12091 |         PUT_WORD (&result_buffer[4], GOOD); | 
 | 12092 |         d = 0; | 
 | 12093 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH) | 
 | 12094 |           d |= LI_CONFERENCING_SUPPORTED; | 
 | 12095 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC) | 
 | 12096 |           d |= LI_MONITORING_SUPPORTED; | 
 | 12097 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH) | 
 | 12098 |           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED; | 
 | 12099 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 12100 |           d |= LI_CROSS_CONTROLLER_SUPPORTED; | 
 | 12101 |         PUT_DWORD (&result_buffer[6], d); | 
 | 12102 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 12103 |         { | 
 | 12104 |           d = 0; | 
 | 12105 |           for (i = 0; i < li_total_channels; i++) | 
 | 12106 |           { | 
 | 12107 |             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 12108 |              && (li_config_table[i].adapter->li_pri | 
 | 12109 |               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI))) | 
 | 12110 |             { | 
 | 12111 |               d++; | 
 | 12112 |             } | 
 | 12113 |           } | 
 | 12114 |         } | 
 | 12115 |         else | 
 | 12116 |         { | 
 | 12117 |           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI; | 
 | 12118 |         } | 
 | 12119 |         PUT_DWORD (&result_buffer[10], d / 2); | 
 | 12120 |         PUT_DWORD (&result_buffer[14], d); | 
 | 12121 |       } | 
 | 12122 |       else | 
 | 12123 |       { | 
 | 12124 |         result_buffer[0] = 25; | 
 | 12125 |         result_buffer[3] = 22; | 
 | 12126 |         PUT_WORD (&result_buffer[4], GOOD); | 
 | 12127 |         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED; | 
 | 12128 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC) | 
 | 12129 |           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED; | 
 | 12130 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH) | 
 | 12131 |           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED; | 
 | 12132 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC) | 
 | 12133 |           d |= LI2_PC_LOOPING_SUPPORTED; | 
 | 12134 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 12135 |           d |= LI2_CROSS_CONTROLLER_SUPPORTED; | 
 | 12136 |         PUT_DWORD (&result_buffer[6], d); | 
 | 12137 |         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI; | 
 | 12138 |         PUT_DWORD (&result_buffer[10], d / 2); | 
 | 12139 |         PUT_DWORD (&result_buffer[14], d - 1); | 
 | 12140 |         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 12141 |         { | 
 | 12142 |           d = 0; | 
 | 12143 |           for (i = 0; i < li_total_channels; i++) | 
 | 12144 |           { | 
 | 12145 |             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | 
 | 12146 |              && (li_config_table[i].adapter->li_pri | 
 | 12147 |               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI))) | 
 | 12148 |             { | 
 | 12149 |               d++; | 
 | 12150 |             } | 
 | 12151 |           } | 
 | 12152 |         } | 
 | 12153 |         PUT_DWORD (&result_buffer[18], d / 2); | 
 | 12154 |         PUT_DWORD (&result_buffer[22], d - 1); | 
 | 12155 |       } | 
 | 12156 |       break; | 
 | 12157 |  | 
 | 12158 |     case LI_REQ_CONNECT: | 
 | 12159 |       if (li_parms[1].length == 8) | 
 | 12160 |       { | 
 | 12161 |         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC; | 
 | 12162 |         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms)) | 
 | 12163 |         { | 
 | 12164 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12165 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12166 |           Info = _WRONG_MESSAGE_FORMAT; | 
 | 12167 |           break; | 
 | 12168 |         } | 
 | 12169 |         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff; | 
 | 12170 |         li_flags = GET_DWORD (li_req_parms[1].info); | 
 | 12171 |         Info = li_check_main_plci (Id, plci); | 
 | 12172 |         result_buffer[0] = 9; | 
 | 12173 |         result_buffer[3] = 6; | 
 | 12174 |         PUT_DWORD (&result_buffer[4], plci_b_id); | 
 | 12175 |         PUT_WORD (&result_buffer[8], GOOD); | 
 | 12176 |         if (Info != GOOD) | 
 | 12177 |           break; | 
 | 12178 |         result = plci->saved_msg.info; | 
 | 12179 |         for (i = 0; i <= result_buffer[0]; i++) | 
 | 12180 |           result[i] = result_buffer[i]; | 
 | 12181 |         plci_b_write_pos = plci->li_plci_b_write_pos; | 
 | 12182 |         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]); | 
 | 12183 |         if (plci_b == NULL) | 
 | 12184 |           break; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12185 |         li_update_connect (Id, a, plci, plci_b_id, true, li_flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12186 |         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG; | 
 | 12187 |         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12188 |         plci->li_plci_b_write_pos = plci_b_write_pos; | 
 | 12189 |       } | 
 | 12190 |       else | 
 | 12191 |       { | 
 | 12192 |         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC; | 
 | 12193 |         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms)) | 
 | 12194 |         { | 
 | 12195 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12196 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12197 |           Info = _WRONG_MESSAGE_FORMAT; | 
 | 12198 |           break; | 
 | 12199 |         } | 
 | 12200 |         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A); | 
 | 12201 |         Info = li_check_main_plci (Id, plci); | 
 | 12202 |         result_buffer[0] = 7; | 
 | 12203 |         result_buffer[3] = 4; | 
 | 12204 |         PUT_WORD (&result_buffer[4], Info); | 
 | 12205 |         result_buffer[6] = 0; | 
 | 12206 |         if (Info != GOOD) | 
 | 12207 |           break; | 
 | 12208 |         result = plci->saved_msg.info; | 
 | 12209 |         for (i = 0; i <= result_buffer[0]; i++) | 
 | 12210 |           result[i] = result_buffer[i]; | 
 | 12211 |         plci_b_write_pos = plci->li_plci_b_write_pos; | 
 | 12212 |         participant_parms_pos = 0; | 
 | 12213 |         result_pos = 7; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12214 |         li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12215 |         while (participant_parms_pos < li_req_parms[1].length) | 
 | 12216 |         { | 
 | 12217 |           result[result_pos] = 6; | 
 | 12218 |           result_pos += 7; | 
 | 12219 |           PUT_DWORD (&result[result_pos - 6], 0); | 
 | 12220 |           PUT_WORD (&result[result_pos - 2], GOOD); | 
 | 12221 |           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos], | 
 | 12222 |             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct)) | 
 | 12223 |           { | 
 | 12224 |             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12225 |               UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12226 |             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | 
 | 12227 |             break; | 
 | 12228 |           } | 
 | 12229 |           if (api_parse (&li_participant_struct[0].info[1], | 
 | 12230 |             li_participant_struct[0].length, "dd", li_participant_parms)) | 
 | 12231 |           { | 
 | 12232 |             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12233 |               UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12234 |             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | 
 | 12235 |             break; | 
 | 12236 |           } | 
 | 12237 |           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff; | 
 | 12238 |           li_flags = GET_DWORD (li_participant_parms[1].info); | 
 | 12239 |           PUT_DWORD (&result[result_pos - 6], plci_b_id); | 
 | 12240 |           if (sizeof(result) - result_pos < 7) | 
 | 12241 |           { | 
 | 12242 |             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun", | 
 | 12243 |               UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12244 |             PUT_WORD (&result[result_pos - 2], _WRONG_STATE); | 
 | 12245 |             break; | 
 | 12246 |           } | 
 | 12247 |           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]); | 
 | 12248 |           if (plci_b != NULL) | 
 | 12249 |           { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12250 |             li2_update_connect (Id, a, plci, plci_b_id, true, li_flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12251 |             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | | 
 | 12252 |               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A | | 
 | 12253 |               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG); | 
 | 12254 |             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12255 |           } | 
 | 12256 |           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) - | 
 | 12257 |             (&li_req_parms[1].info[1])); | 
 | 12258 |         } | 
 | 12259 |         result[0] = (byte)(result_pos - 1); | 
 | 12260 |         result[3] = (byte)(result_pos - 4); | 
 | 12261 |         result[6] = (byte)(result_pos - 7); | 
 | 12262 |         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1; | 
 | 12263 |         if ((plci_b_write_pos == plci->li_plci_b_read_pos) | 
 | 12264 |          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)) | 
 | 12265 |         { | 
 | 12266 |           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG; | 
 | 12267 |           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12268 |         } | 
 | 12269 |         else | 
 | 12270 |           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG; | 
 | 12271 |         plci->li_plci_b_write_pos = plci_b_write_pos; | 
 | 12272 |       } | 
 | 12273 |       mixer_calculate_coefs (a); | 
 | 12274 |       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12275 |       mixer_notify_update (plci, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12276 |       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | 
 | 12277 |         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); | 
 | 12278 |       plci->command = 0; | 
 | 12279 |       plci->li_cmd = GET_WORD (li_parms[0].info); | 
 | 12280 |       start_internal_command (Id, plci, mixer_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12281 |       return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12282 |  | 
 | 12283 |     case LI_REQ_DISCONNECT: | 
 | 12284 |       if (li_parms[1].length == 4) | 
 | 12285 |       { | 
 | 12286 |         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC; | 
 | 12287 |         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms)) | 
 | 12288 |         { | 
 | 12289 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12290 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12291 |           Info = _WRONG_MESSAGE_FORMAT; | 
 | 12292 |           break; | 
 | 12293 |         } | 
 | 12294 |         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff; | 
 | 12295 |         Info = li_check_main_plci (Id, plci); | 
 | 12296 |         result_buffer[0] = 9; | 
 | 12297 |         result_buffer[3] = 6; | 
 | 12298 |         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info)); | 
 | 12299 |         PUT_WORD (&result_buffer[8], GOOD); | 
 | 12300 |         if (Info != GOOD) | 
 | 12301 |           break; | 
 | 12302 |         result = plci->saved_msg.info; | 
 | 12303 |         for (i = 0; i <= result_buffer[0]; i++) | 
 | 12304 |           result[i] = result_buffer[i]; | 
 | 12305 |         plci_b_write_pos = plci->li_plci_b_write_pos; | 
 | 12306 |         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]); | 
 | 12307 |         if (plci_b == NULL) | 
 | 12308 |           break; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12309 |         li_update_connect (Id, a, plci, plci_b_id, false, 0); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12310 |         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG; | 
 | 12311 |         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12312 |         plci->li_plci_b_write_pos = plci_b_write_pos; | 
 | 12313 |       } | 
 | 12314 |       else | 
 | 12315 |       { | 
 | 12316 |         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC; | 
 | 12317 |         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms)) | 
 | 12318 |         { | 
 | 12319 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12320 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12321 |           Info = _WRONG_MESSAGE_FORMAT; | 
 | 12322 |           break; | 
 | 12323 |         } | 
 | 12324 |         Info = li_check_main_plci (Id, plci); | 
 | 12325 |         result_buffer[0] = 7; | 
 | 12326 |         result_buffer[3] = 4; | 
 | 12327 |         PUT_WORD (&result_buffer[4], Info); | 
 | 12328 |         result_buffer[6] = 0; | 
 | 12329 |         if (Info != GOOD) | 
 | 12330 |           break; | 
 | 12331 |         result = plci->saved_msg.info; | 
 | 12332 |         for (i = 0; i <= result_buffer[0]; i++) | 
 | 12333 |           result[i] = result_buffer[i]; | 
 | 12334 |         plci_b_write_pos = plci->li_plci_b_write_pos; | 
 | 12335 |         participant_parms_pos = 0; | 
 | 12336 |         result_pos = 7; | 
 | 12337 |         while (participant_parms_pos < li_req_parms[0].length) | 
 | 12338 |         { | 
 | 12339 |           result[result_pos] = 6; | 
 | 12340 |           result_pos += 7; | 
 | 12341 |           PUT_DWORD (&result[result_pos - 6], 0); | 
 | 12342 |           PUT_WORD (&result[result_pos - 2], GOOD); | 
 | 12343 |           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos], | 
 | 12344 |             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct)) | 
 | 12345 |           { | 
 | 12346 |             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12347 |               UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12348 |             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | 
 | 12349 |             break; | 
 | 12350 |           } | 
 | 12351 |           if (api_parse (&li_participant_struct[0].info[1], | 
 | 12352 |             li_participant_struct[0].length, "d", li_participant_parms)) | 
 | 12353 |           { | 
 | 12354 |             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12355 |               UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12356 |             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | 
 | 12357 |             break; | 
 | 12358 |           } | 
 | 12359 |           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff; | 
 | 12360 |           PUT_DWORD (&result[result_pos - 6], plci_b_id); | 
 | 12361 |           if (sizeof(result) - result_pos < 7) | 
 | 12362 |           { | 
 | 12363 |             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun", | 
 | 12364 |               UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12365 |             PUT_WORD (&result[result_pos - 2], _WRONG_STATE); | 
 | 12366 |             break; | 
 | 12367 |           } | 
 | 12368 |           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]); | 
 | 12369 |           if (plci_b != NULL) | 
 | 12370 |           { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12371 |             li2_update_connect (Id, a, plci, plci_b_id, false, 0); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12372 |             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG; | 
 | 12373 |             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12374 |           } | 
 | 12375 |           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) - | 
 | 12376 |             (&li_req_parms[0].info[1])); | 
 | 12377 |         } | 
 | 12378 |         result[0] = (byte)(result_pos - 1); | 
 | 12379 |         result[3] = (byte)(result_pos - 4); | 
 | 12380 |         result[6] = (byte)(result_pos - 7); | 
 | 12381 |         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1; | 
 | 12382 |         if ((plci_b_write_pos == plci->li_plci_b_read_pos) | 
 | 12383 |          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)) | 
 | 12384 |         { | 
 | 12385 |           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG; | 
 | 12386 |           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12387 |         } | 
 | 12388 |         else | 
 | 12389 |           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG; | 
 | 12390 |         plci->li_plci_b_write_pos = plci_b_write_pos; | 
 | 12391 |       } | 
 | 12392 |       mixer_calculate_coefs (a); | 
 | 12393 |       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12394 |       mixer_notify_update (plci, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12395 |       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | 
 | 12396 |         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); | 
 | 12397 |       plci->command = 0; | 
 | 12398 |       plci->li_cmd = GET_WORD (li_parms[0].info); | 
 | 12399 |       start_internal_command (Id, plci, mixer_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12400 |       return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12401 |  | 
 | 12402 |     case LI_REQ_SILENT_UPDATE: | 
 | 12403 |       if (!plci || !plci->State | 
 | 12404 |        || !plci->NL.Id || plci->nl_remove_id | 
 | 12405 |        || (plci->li_bchannel_id == 0) | 
 | 12406 |        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci)) | 
 | 12407 |       { | 
 | 12408 |         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | 
 | 12409 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12410 |         return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12411 |       } | 
 | 12412 |       plci_b_write_pos = plci->li_plci_b_write_pos; | 
 | 12413 |       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | 
 | 12414 |         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2) | 
 | 12415 |       { | 
 | 12416 |         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | 
 | 12417 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12418 |         return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12419 |       } | 
 | 12420 |       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1; | 
 | 12421 |       if ((plci_b_write_pos == plci->li_plci_b_read_pos) | 
 | 12422 |        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)) | 
 | 12423 |       { | 
 | 12424 |         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG; | 
 | 12425 |         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12426 |       } | 
 | 12427 |       else | 
 | 12428 |         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG; | 
 | 12429 |       plci->li_plci_b_write_pos = plci_b_write_pos; | 
 | 12430 |       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel; | 
 | 12431 |       plci->command = 0; | 
 | 12432 |       plci->li_cmd = GET_WORD (li_parms[0].info); | 
 | 12433 |       start_internal_command (Id, plci, mixer_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12434 |       return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12435 |  | 
 | 12436 |     default: | 
 | 12437 |       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x", | 
 | 12438 |         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info))); | 
 | 12439 |       Info = _FACILITY_NOT_SUPPORTED; | 
 | 12440 |     } | 
 | 12441 |   } | 
 | 12442 |   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | 
 | 12443 |     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12444 |   return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12445 | } | 
 | 12446 |  | 
 | 12447 |  | 
 | 12448 | static void mixer_indication_coefs_set (dword Id, PLCI   *plci) | 
 | 12449 | { | 
 | 12450 |   dword d; | 
 | 12451 |   DIVA_CAPI_ADAPTER   *a; | 
 | 12452 |     byte result[12]; | 
 | 12453 |  | 
 | 12454 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set", | 
 | 12455 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12456 |  | 
 | 12457 |   a = plci->adapter; | 
 | 12458 |   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos) | 
 | 12459 |   { | 
 | 12460 |     do | 
 | 12461 |     { | 
 | 12462 |       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos]; | 
 | 12463 |       if (!(d & LI_PLCI_B_SKIP_FLAG)) | 
 | 12464 |       { | 
 | 12465 |         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC) | 
 | 12466 |         { | 
 | 12467 |           if (d & LI_PLCI_B_DISC_FLAG) | 
 | 12468 |           { | 
 | 12469 |             result[0] = 5; | 
 | 12470 |             PUT_WORD (&result[1], LI_IND_DISCONNECT); | 
 | 12471 |             result[3] = 2; | 
 | 12472 |             PUT_WORD (&result[4], _LI_USER_INITIATED); | 
 | 12473 |           } | 
 | 12474 |           else | 
 | 12475 |           { | 
 | 12476 |             result[0] = 7; | 
 | 12477 |             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE); | 
 | 12478 |             result[3] = 4; | 
 | 12479 |             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); | 
 | 12480 |           } | 
 | 12481 |         } | 
 | 12482 |         else | 
 | 12483 |         { | 
 | 12484 |           if (d & LI_PLCI_B_DISC_FLAG) | 
 | 12485 |           { | 
 | 12486 |             result[0] = 9; | 
 | 12487 |             PUT_WORD (&result[1], LI_IND_DISCONNECT); | 
 | 12488 |             result[3] = 6; | 
 | 12489 |             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); | 
 | 12490 |             PUT_WORD (&result[8], _LI_USER_INITIATED); | 
 | 12491 |           } | 
 | 12492 |           else | 
 | 12493 |           { | 
 | 12494 |             result[0] = 7; | 
 | 12495 |             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE); | 
 | 12496 |             result[3] = 4; | 
 | 12497 |             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); | 
 | 12498 |           } | 
 | 12499 |         } | 
 | 12500 |         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, | 
 | 12501 |           "ws", SELECTOR_LINE_INTERCONNECT, result); | 
 | 12502 |       } | 
 | 12503 |       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? | 
 | 12504 |         0 : plci->li_plci_b_read_pos + 1; | 
 | 12505 |     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)); | 
 | 12506 |   } | 
 | 12507 | } | 
 | 12508 |  | 
 | 12509 |  | 
 | 12510 | static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length) | 
 | 12511 | { | 
 | 12512 |   word i, j, ch; | 
 | 12513 |   struct xconnect_transfer_address_s s,   *p; | 
 | 12514 |   DIVA_CAPI_ADAPTER   *a; | 
 | 12515 |  | 
 | 12516 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d", | 
 | 12517 |     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length)); | 
 | 12518 |  | 
 | 12519 |   a = plci->adapter; | 
 | 12520 |   i = 1; | 
 | 12521 |   for (i = 1; i < length; i += 16) | 
 | 12522 |   { | 
 | 12523 |     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24); | 
 | 12524 |     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24); | 
 | 12525 |     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24); | 
 | 12526 |     ch = msg[i+12] | (msg[i+13] << 8); | 
 | 12527 |     j = ch & XCONNECT_CHANNEL_NUMBER_MASK; | 
 | 12528 |     if (!a->li_pri && (plci->li_bchannel_id == 2)) | 
 | 12529 |       j = 1 - j; | 
 | 12530 |     j += a->li_base; | 
 | 12531 |     if (ch & XCONNECT_CHANNEL_PORT_PC) | 
 | 12532 |       p = &(li_config_table[j].send_pc); | 
 | 12533 |     else | 
 | 12534 |       p = &(li_config_table[j].send_b); | 
 | 12535 |     p->card_address.low = s.card_address.low; | 
 | 12536 |     p->card_address.high = s.card_address.high; | 
 | 12537 |     p->offset = s.offset; | 
 | 12538 |     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET; | 
 | 12539 |   } | 
 | 12540 |   if (plci->internal_command_queue[0] | 
 | 12541 |    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2) | 
 | 12542 |     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3) | 
 | 12543 |     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4))) | 
 | 12544 |   { | 
 | 12545 |     (*(plci->internal_command_queue[0]))(Id, plci, 0); | 
 | 12546 |     if (!plci->internal_command) | 
 | 12547 |       next_internal_command (Id, plci); | 
 | 12548 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12549 |   mixer_notify_update (plci, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12550 | } | 
 | 12551 |  | 
 | 12552 |  | 
 | 12553 | static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length) | 
 | 12554 | { | 
 | 12555 |  | 
 | 12556 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d", | 
 | 12557 |     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length)); | 
 | 12558 |  | 
 | 12559 | } | 
 | 12560 |  | 
 | 12561 |  | 
 | 12562 | static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id) | 
 | 12563 | { | 
 | 12564 |   word plci_b_write_pos; | 
 | 12565 |  | 
 | 12566 |   plci_b_write_pos = plci->li_plci_b_write_pos; | 
 | 12567 |   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | 
 | 12568 |     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1) | 
 | 12569 |   { | 
 | 12570 |     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | 
 | 12571 |       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 12572 |       (char   *)(FILE_), __LINE__)); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12573 |     return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12574 |   } | 
 | 12575 |   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG; | 
 | 12576 |   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | 
 | 12577 |   plci->li_plci_b_write_pos = plci_b_write_pos; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12578 |   return (true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12579 | } | 
 | 12580 |  | 
 | 12581 |  | 
 | 12582 | static void mixer_remove (PLCI   *plci) | 
 | 12583 | { | 
 | 12584 |   DIVA_CAPI_ADAPTER   *a; | 
 | 12585 |   PLCI   *notify_plci; | 
 | 12586 |   dword plci_b_id; | 
 | 12587 |   word i, j; | 
 | 12588 |  | 
 | 12589 |   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove", | 
 | 12590 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 12591 |     (char   *)(FILE_), __LINE__)); | 
 | 12592 |  | 
 | 12593 |   a = plci->adapter; | 
 | 12594 |   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id); | 
 | 12595 |   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED) | 
 | 12596 |   { | 
 | 12597 |     if ((plci->li_bchannel_id != 0) | 
 | 12598 |      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 12599 |     { | 
 | 12600 |       i = a->li_base + (plci->li_bchannel_id - 1); | 
 | 12601 |       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED) | 
 | 12602 |       { | 
 | 12603 |         for (j = 0; j < li_total_channels; j++) | 
 | 12604 |         { | 
 | 12605 |           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | 
 | 12606 |            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)) | 
 | 12607 |           { | 
 | 12608 |             notify_plci = li_config_table[j].plci; | 
 | 12609 |             if ((notify_plci != NULL) | 
 | 12610 |              && (notify_plci != plci) | 
 | 12611 |              && (notify_plci->appl != NULL) | 
 | 12612 |              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC) | 
 | 12613 |              && (notify_plci->State) | 
 | 12614 |              && notify_plci->NL.Id && !notify_plci->nl_remove_id) | 
 | 12615 |             { | 
 | 12616 |               mixer_notify_source_removed (notify_plci, plci_b_id); | 
 | 12617 |             } | 
 | 12618 |           } | 
 | 12619 |         } | 
 | 12620 |         mixer_clear_config (plci); | 
 | 12621 |         mixer_calculate_coefs (a); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12622 |         mixer_notify_update (plci, true); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12623 |       } | 
 | 12624 |       li_config_table[i].plci = NULL; | 
 | 12625 |       plci->li_bchannel_id = 0; | 
 | 12626 |     } | 
 | 12627 |   } | 
 | 12628 | } | 
 | 12629 |  | 
 | 12630 |  | 
 | 12631 | /*------------------------------------------------------------------*/ | 
 | 12632 | /* Echo canceller facilities                                        */ | 
 | 12633 | /*------------------------------------------------------------------*/ | 
 | 12634 |  | 
 | 12635 |  | 
 | 12636 | static void ec_write_parameters (PLCI   *plci) | 
 | 12637 | { | 
 | 12638 |   word w; | 
 | 12639 |     byte parameter_buffer[6]; | 
 | 12640 |  | 
 | 12641 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters", | 
 | 12642 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 12643 |     (char   *)(FILE_), __LINE__)); | 
 | 12644 |  | 
 | 12645 |   parameter_buffer[0] = 5; | 
 | 12646 |   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS; | 
 | 12647 |   PUT_WORD (¶meter_buffer[2], plci->ec_idi_options); | 
 | 12648 |   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS; | 
 | 12649 |   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length; | 
 | 12650 |   PUT_WORD (¶meter_buffer[4], w); | 
 | 12651 |   add_p (plci, FTY, parameter_buffer); | 
 | 12652 |   sig_req (plci, TEL_CTRL, 0); | 
 | 12653 |   send_req (plci); | 
 | 12654 | } | 
 | 12655 |  | 
 | 12656 |  | 
 | 12657 | static void ec_clear_config (PLCI   *plci) | 
 | 12658 | { | 
 | 12659 |  | 
 | 12660 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config", | 
 | 12661 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 12662 |     (char   *)(FILE_), __LINE__)); | 
 | 12663 |  | 
 | 12664 |   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER | | 
 | 12665 |     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING; | 
 | 12666 |   plci->ec_tail_length = 0; | 
 | 12667 | } | 
 | 12668 |  | 
 | 12669 |  | 
 | 12670 | static void ec_prepare_switch (dword Id, PLCI   *plci) | 
 | 12671 | { | 
 | 12672 |  | 
 | 12673 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch", | 
 | 12674 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12675 |  | 
 | 12676 | } | 
 | 12677 |  | 
 | 12678 |  | 
 | 12679 | static word ec_save_config (dword Id, PLCI   *plci, byte Rc) | 
 | 12680 | { | 
 | 12681 |  | 
 | 12682 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d", | 
 | 12683 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 12684 |  | 
 | 12685 |   return (GOOD); | 
 | 12686 | } | 
 | 12687 |  | 
 | 12688 |  | 
 | 12689 | static word ec_restore_config (dword Id, PLCI   *plci, byte Rc) | 
 | 12690 | { | 
 | 12691 |   word Info; | 
 | 12692 |  | 
 | 12693 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d", | 
 | 12694 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 12695 |  | 
 | 12696 |   Info = GOOD; | 
 | 12697 |   if (plci->B1_facilities & B1_FACILITY_EC) | 
 | 12698 |   { | 
 | 12699 |     switch (plci->adjust_b_state) | 
 | 12700 |     { | 
 | 12701 |     case ADJUST_B_RESTORE_EC_1: | 
 | 12702 |       plci->internal_command = plci->adjust_b_command; | 
 | 12703 |       if (plci->sig_req) | 
 | 12704 |       { | 
 | 12705 |         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1; | 
 | 12706 |         break; | 
 | 12707 |       } | 
 | 12708 |       ec_write_parameters (plci); | 
 | 12709 |       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2; | 
 | 12710 |       break; | 
 | 12711 |     case ADJUST_B_RESTORE_EC_2: | 
 | 12712 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 12713 |       { | 
 | 12714 |         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x", | 
 | 12715 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 12716 |         Info = _WRONG_STATE; | 
 | 12717 |         break; | 
 | 12718 |       } | 
 | 12719 |       break; | 
 | 12720 |     } | 
 | 12721 |   } | 
 | 12722 |   return (Info); | 
 | 12723 | } | 
 | 12724 |  | 
 | 12725 |  | 
 | 12726 | static void ec_command (dword Id, PLCI   *plci, byte Rc) | 
 | 12727 | { | 
 | 12728 |   word internal_command, Info; | 
 | 12729 |     byte result[8]; | 
 | 12730 |  | 
 | 12731 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d", | 
 | 12732 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command, | 
 | 12733 |     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length)); | 
 | 12734 |  | 
 | 12735 |   Info = GOOD; | 
 | 12736 |   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) | 
 | 12737 |   { | 
 | 12738 |     result[0] = 2; | 
 | 12739 |     PUT_WORD (&result[1], EC_SUCCESS); | 
 | 12740 |   } | 
 | 12741 |   else | 
 | 12742 |   { | 
 | 12743 |     result[0] = 5; | 
 | 12744 |     PUT_WORD (&result[1], plci->ec_cmd); | 
 | 12745 |     result[3] = 2; | 
 | 12746 |     PUT_WORD (&result[4], GOOD); | 
 | 12747 |   } | 
 | 12748 |   internal_command = plci->internal_command; | 
 | 12749 |   plci->internal_command = 0; | 
 | 12750 |   switch (plci->ec_cmd) | 
 | 12751 |   { | 
 | 12752 |   case EC_ENABLE_OPERATION: | 
 | 12753 |   case EC_FREEZE_COEFFICIENTS: | 
 | 12754 |   case EC_RESUME_COEFFICIENT_UPDATE: | 
 | 12755 |   case EC_RESET_COEFFICIENTS: | 
 | 12756 |     switch (internal_command) | 
 | 12757 |     { | 
 | 12758 |     default: | 
 | 12759 |       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | 
 | 12760 |         B1_FACILITY_EC), EC_COMMAND_1); | 
 | 12761 |     case EC_COMMAND_1: | 
 | 12762 |       if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 12763 |       { | 
 | 12764 |         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed", | 
 | 12765 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12766 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 12767 |         break; | 
 | 12768 |       } | 
 | 12769 |       if (plci->internal_command) | 
 | 12770 |         return; | 
 | 12771 |     case EC_COMMAND_2: | 
 | 12772 |       if (plci->sig_req) | 
 | 12773 |       { | 
 | 12774 |         plci->internal_command = EC_COMMAND_2; | 
 | 12775 |         return; | 
 | 12776 |       } | 
 | 12777 |       plci->internal_command = EC_COMMAND_3; | 
 | 12778 |       ec_write_parameters (plci); | 
 | 12779 |       return; | 
 | 12780 |     case EC_COMMAND_3: | 
 | 12781 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 12782 |       { | 
 | 12783 |         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x", | 
 | 12784 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 12785 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 12786 |         break; | 
 | 12787 |       } | 
 | 12788 |       break; | 
 | 12789 |     } | 
 | 12790 |     break; | 
 | 12791 |  | 
 | 12792 |   case EC_DISABLE_OPERATION: | 
 | 12793 |     switch (internal_command) | 
 | 12794 |     { | 
 | 12795 |     default: | 
 | 12796 |     case EC_COMMAND_1: | 
 | 12797 |       if (plci->B1_facilities & B1_FACILITY_EC) | 
 | 12798 |       { | 
 | 12799 |         if (plci->sig_req) | 
 | 12800 |         { | 
 | 12801 |           plci->internal_command = EC_COMMAND_1; | 
 | 12802 |           return; | 
 | 12803 |         } | 
 | 12804 |         plci->internal_command = EC_COMMAND_2; | 
 | 12805 |         ec_write_parameters (plci); | 
 | 12806 |         return; | 
 | 12807 |       } | 
 | 12808 |       Rc = OK; | 
 | 12809 |     case EC_COMMAND_2: | 
 | 12810 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 12811 |       { | 
 | 12812 |         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x", | 
 | 12813 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 12814 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 12815 |         break; | 
 | 12816 |       } | 
 | 12817 |       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities & | 
 | 12818 |         ~B1_FACILITY_EC), EC_COMMAND_3); | 
 | 12819 |     case EC_COMMAND_3: | 
 | 12820 |       if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 12821 |       { | 
 | 12822 |         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed", | 
 | 12823 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12824 |         Info = _FACILITY_NOT_SUPPORTED; | 
 | 12825 |         break; | 
 | 12826 |       } | 
 | 12827 |       if (plci->internal_command) | 
 | 12828 |         return; | 
 | 12829 |       break; | 
 | 12830 |     } | 
 | 12831 |     break; | 
 | 12832 |   } | 
 | 12833 |   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number, | 
 | 12834 |     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ? | 
 | 12835 |     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result); | 
 | 12836 | } | 
 | 12837 |  | 
 | 12838 |  | 
 | 12839 | static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg) | 
 | 12840 | { | 
 | 12841 |   word Info; | 
 | 12842 |   word opt; | 
 | 12843 |     API_PARSE ec_parms[3]; | 
 | 12844 |     byte result[16]; | 
 | 12845 |  | 
 | 12846 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_request", | 
 | 12847 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12848 |  | 
 | 12849 |   Info = GOOD; | 
 | 12850 |   result[0] = 0; | 
 | 12851 |   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER))) | 
 | 12852 |   { | 
 | 12853 |     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | 
 | 12854 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12855 |     Info = _FACILITY_NOT_SUPPORTED; | 
 | 12856 |   } | 
 | 12857 |   else | 
 | 12858 |   { | 
 | 12859 |     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) | 
 | 12860 |     { | 
 | 12861 |       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms)) | 
 | 12862 |       { | 
 | 12863 |         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12864 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12865 |         Info = _WRONG_MESSAGE_FORMAT; | 
 | 12866 |       } | 
 | 12867 |       else | 
 | 12868 |       { | 
 | 12869 |         if (plci == NULL) | 
 | 12870 |         { | 
 | 12871 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | 
 | 12872 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12873 |           Info = _WRONG_IDENTIFIER; | 
 | 12874 |         } | 
 | 12875 |         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id) | 
 | 12876 |         { | 
 | 12877 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | 
 | 12878 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12879 |           Info = _WRONG_STATE; | 
 | 12880 |         } | 
 | 12881 |         else | 
 | 12882 |         { | 
 | 12883 |           plci->command = 0; | 
 | 12884 |           plci->ec_cmd = GET_WORD (ec_parms[0].info); | 
 | 12885 |           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS); | 
 | 12886 |           result[0] = 2; | 
 | 12887 |           PUT_WORD (&result[1], EC_SUCCESS); | 
 | 12888 |           if (msg[1].length >= 4) | 
 | 12889 |           { | 
 | 12890 |             opt = GET_WORD (&ec_parms[0].info[2]); | 
 | 12891 |             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING | | 
 | 12892 |               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS); | 
 | 12893 |             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING)) | 
 | 12894 |               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING; | 
 | 12895 |             if (opt & EC_DETECT_DISABLE_TONE) | 
 | 12896 |               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR; | 
 | 12897 |             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS)) | 
 | 12898 |               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS; | 
 | 12899 |             if (msg[1].length >= 6) | 
 | 12900 |             { | 
 | 12901 |               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]); | 
 | 12902 |             } | 
 | 12903 |           } | 
 | 12904 |           switch (plci->ec_cmd) | 
 | 12905 |           { | 
 | 12906 |           case EC_ENABLE_OPERATION: | 
 | 12907 |             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS; | 
 | 12908 |             start_internal_command (Id, plci, ec_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12909 |             return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12910 |  | 
 | 12911 |           case EC_DISABLE_OPERATION: | 
 | 12912 |             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER | | 
 | 12913 |               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING | | 
 | 12914 |               LEC_RESET_COEFFICIENTS; | 
 | 12915 |             start_internal_command (Id, plci, ec_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12916 |             return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12917 |  | 
 | 12918 |           case EC_FREEZE_COEFFICIENTS: | 
 | 12919 |             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS; | 
 | 12920 |             start_internal_command (Id, plci, ec_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12921 |             return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12922 |  | 
 | 12923 |           case EC_RESUME_COEFFICIENT_UPDATE: | 
 | 12924 |             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS; | 
 | 12925 |             start_internal_command (Id, plci, ec_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12926 |             return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12927 |  | 
 | 12928 |           case EC_RESET_COEFFICIENTS: | 
 | 12929 |             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS; | 
 | 12930 |             start_internal_command (Id, plci, ec_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 12931 |             return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12932 |  | 
 | 12933 |           default: | 
 | 12934 |             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x", | 
 | 12935 |               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd)); | 
 | 12936 |             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION); | 
 | 12937 |           } | 
 | 12938 |         } | 
 | 12939 |       } | 
 | 12940 |     } | 
 | 12941 |     else | 
 | 12942 |     { | 
 | 12943 |       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms)) | 
 | 12944 |       { | 
 | 12945 |         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | 
 | 12946 |           UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12947 |         Info = _WRONG_MESSAGE_FORMAT; | 
 | 12948 |       } | 
 | 12949 |       else | 
 | 12950 |       { | 
 | 12951 |         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES) | 
 | 12952 |         { | 
 | 12953 |           result[0] = 11; | 
 | 12954 |           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES); | 
 | 12955 |           result[3] = 8; | 
 | 12956 |           PUT_WORD (&result[4], GOOD); | 
 | 12957 |           PUT_WORD (&result[6], 0x0007); | 
 | 12958 |           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH); | 
 | 12959 |           PUT_WORD (&result[10], 0); | 
 | 12960 |         } | 
 | 12961 |         else if (plci == NULL) | 
 | 12962 |         { | 
 | 12963 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | 
 | 12964 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12965 |           Info = _WRONG_IDENTIFIER; | 
 | 12966 |         } | 
 | 12967 |         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id) | 
 | 12968 |         { | 
 | 12969 |           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | 
 | 12970 |             UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 12971 |           Info = _WRONG_STATE; | 
 | 12972 |         } | 
 | 12973 |         else | 
 | 12974 |         { | 
 | 12975 |           plci->command = 0; | 
 | 12976 |           plci->ec_cmd = GET_WORD (ec_parms[0].info); | 
 | 12977 |           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS); | 
 | 12978 |           result[0] = 5; | 
 | 12979 |           PUT_WORD (&result[1], plci->ec_cmd); | 
 | 12980 |           result[3] = 2; | 
 | 12981 |           PUT_WORD (&result[4], GOOD); | 
 | 12982 |           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING | | 
 | 12983 |             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS); | 
 | 12984 |           plci->ec_tail_length = 0; | 
 | 12985 |           if (ec_parms[1].length >= 2) | 
 | 12986 |           { | 
 | 12987 |             opt = GET_WORD (&ec_parms[1].info[1]); | 
 | 12988 |             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING) | 
 | 12989 |               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING; | 
 | 12990 |             if (opt & EC_DETECT_DISABLE_TONE) | 
 | 12991 |               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR; | 
 | 12992 |             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS)) | 
 | 12993 |               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS; | 
 | 12994 |             if (ec_parms[1].length >= 4) | 
 | 12995 |             { | 
 | 12996 |               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]); | 
 | 12997 |             } | 
 | 12998 |           } | 
 | 12999 |           switch (plci->ec_cmd) | 
 | 13000 |           { | 
 | 13001 |           case EC_ENABLE_OPERATION: | 
 | 13002 |             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS; | 
 | 13003 |             start_internal_command (Id, plci, ec_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 13004 |             return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13005 |  | 
 | 13006 |           case EC_DISABLE_OPERATION: | 
 | 13007 |             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER | | 
 | 13008 |               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING | | 
 | 13009 |               LEC_RESET_COEFFICIENTS; | 
 | 13010 |             start_internal_command (Id, plci, ec_command); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 13011 |             return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13012 |  | 
 | 13013 |           default: | 
 | 13014 |             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x", | 
 | 13015 |               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd)); | 
 | 13016 |             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP); | 
 | 13017 |           } | 
 | 13018 |         } | 
 | 13019 |       } | 
 | 13020 |     } | 
 | 13021 |   } | 
 | 13022 |   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | 
 | 13023 |     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ? | 
 | 13024 |     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result); | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 13025 |   return (false); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13026 | } | 
 | 13027 |  | 
 | 13028 |  | 
 | 13029 | static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length) | 
 | 13030 | { | 
 | 13031 |     byte result[8]; | 
 | 13032 |  | 
 | 13033 |   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication", | 
 | 13034 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 13035 |  | 
 | 13036 |   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE)) | 
 | 13037 |   { | 
 | 13038 |     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) | 
 | 13039 |     { | 
 | 13040 |       result[0] = 2; | 
 | 13041 |       PUT_WORD (&result[1], 0); | 
 | 13042 |       switch (msg[1]) | 
 | 13043 |       { | 
 | 13044 |       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ: | 
 | 13045 |         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); | 
 | 13046 |         break; | 
 | 13047 |       case LEC_DISABLE_TYPE_REVERSED_2100HZ: | 
 | 13048 |         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ); | 
 | 13049 |         break; | 
 | 13050 |       case LEC_DISABLE_RELEASED: | 
 | 13051 |         PUT_WORD (&result[1], EC_BYPASS_RELEASED); | 
 | 13052 |         break; | 
 | 13053 |       } | 
 | 13054 |     } | 
 | 13055 |     else | 
 | 13056 |     { | 
 | 13057 |       result[0] = 5; | 
 | 13058 |       PUT_WORD (&result[1], EC_BYPASS_INDICATION); | 
 | 13059 |       result[3] = 2; | 
 | 13060 |       PUT_WORD (&result[4], 0); | 
 | 13061 |       switch (msg[1]) | 
 | 13062 |       { | 
 | 13063 |       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ: | 
 | 13064 |         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); | 
 | 13065 |         break; | 
 | 13066 |       case LEC_DISABLE_TYPE_REVERSED_2100HZ: | 
 | 13067 |         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ); | 
 | 13068 |         break; | 
 | 13069 |       case LEC_DISABLE_RELEASED: | 
 | 13070 |         PUT_WORD (&result[4], EC_BYPASS_RELEASED); | 
 | 13071 |         break; | 
 | 13072 |       } | 
 | 13073 |     } | 
 | 13074 |     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ? | 
 | 13075 |       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result); | 
 | 13076 |   } | 
 | 13077 | } | 
 | 13078 |  | 
 | 13079 |  | 
 | 13080 |  | 
 | 13081 | /*------------------------------------------------------------------*/ | 
 | 13082 | /* Advanced voice                                                   */ | 
 | 13083 | /*------------------------------------------------------------------*/ | 
 | 13084 |  | 
 | 13085 | static void adv_voice_write_coefs (PLCI   *plci, word write_command) | 
 | 13086 | { | 
 | 13087 |   DIVA_CAPI_ADAPTER   *a; | 
 | 13088 |   word i; | 
 | 13089 |   byte *p; | 
 | 13090 |  | 
 | 13091 |   word w, n, j, k; | 
 | 13092 |   byte ch_map[MIXER_CHANNELS_BRI]; | 
 | 13093 |  | 
 | 13094 |     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2]; | 
 | 13095 |  | 
 | 13096 |   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d", | 
 | 13097 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13098 |     (char   *)(FILE_), __LINE__, write_command)); | 
 | 13099 |  | 
 | 13100 |   a = plci->adapter; | 
 | 13101 |   p = coef_buffer + 1; | 
 | 13102 |   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS; | 
 | 13103 |   i = 0; | 
 | 13104 |   while (i + sizeof(word) <= a->adv_voice_coef_length) | 
 | 13105 |   { | 
 | 13106 |     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i)); | 
 | 13107 |     p += 2; | 
 | 13108 |     i += 2; | 
 | 13109 |   } | 
 | 13110 |   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word)) | 
 | 13111 |   { | 
 | 13112 |     PUT_WORD (p, 0x8000); | 
 | 13113 |     p += 2; | 
 | 13114 |     i += 2; | 
 | 13115 |   } | 
 | 13116 |  | 
 | 13117 |   if (!a->li_pri && (plci->li_bchannel_id == 0)) | 
 | 13118 |   { | 
 | 13119 |     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL)) | 
 | 13120 |     { | 
 | 13121 |       plci->li_bchannel_id = 1; | 
 | 13122 |       li_config_table[a->li_base].plci = plci; | 
 | 13123 |       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d", | 
 | 13124 |         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13125 |         (char   *)(FILE_), __LINE__, plci->li_bchannel_id)); | 
 | 13126 |     } | 
 | 13127 |     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL)) | 
 | 13128 |     { | 
 | 13129 |       plci->li_bchannel_id = 2; | 
 | 13130 |       li_config_table[a->li_base + 1].plci = plci; | 
 | 13131 |       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d", | 
 | 13132 |         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13133 |         (char   *)(FILE_), __LINE__, plci->li_bchannel_id)); | 
 | 13134 |     } | 
 | 13135 |   } | 
 | 13136 |   if (!a->li_pri && (plci->li_bchannel_id != 0) | 
 | 13137 |    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 13138 |   { | 
 | 13139 |     i = a->li_base + (plci->li_bchannel_id - 1); | 
 | 13140 |     switch (write_command) | 
 | 13141 |     { | 
 | 13142 |     case ADV_VOICE_WRITE_ACTIVATION: | 
 | 13143 |       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | 
 | 13144 |       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | 
 | 13145 |       if (!(plci->B1_facilities & B1_FACILITY_MIXER)) | 
 | 13146 |       { | 
 | 13147 |         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX; | 
 | 13148 |         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR; | 
 | 13149 |       } | 
 | 13150 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | 
 | 13151 |       { | 
 | 13152 |         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX; | 
 | 13153 |         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR; | 
 | 13154 |         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE; | 
 | 13155 |         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE; | 
 | 13156 |       } | 
 | 13157 |       mixer_calculate_coefs (a); | 
 | 13158 |       li_config_table[i].curchnl = li_config_table[i].channel; | 
 | 13159 |       li_config_table[j].curchnl = li_config_table[j].channel; | 
 | 13160 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | 
 | 13161 |         li_config_table[k].curchnl = li_config_table[k].channel; | 
 | 13162 |       break; | 
 | 13163 |  | 
 | 13164 |     case ADV_VOICE_WRITE_DEACTIVATION: | 
 | 13165 |       for (j = 0; j < li_total_channels; j++) | 
 | 13166 |       { | 
 | 13167 |         li_config_table[i].flag_table[j] = 0; | 
 | 13168 |         li_config_table[j].flag_table[i] = 0; | 
 | 13169 |       } | 
 | 13170 |       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | 
 | 13171 |       for (j = 0; j < li_total_channels; j++) | 
 | 13172 |       { | 
 | 13173 |         li_config_table[k].flag_table[j] = 0; | 
 | 13174 |         li_config_table[j].flag_table[k] = 0; | 
 | 13175 |       } | 
 | 13176 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | 
 | 13177 |       { | 
 | 13178 |         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | 
 | 13179 |         for (j = 0; j < li_total_channels; j++) | 
 | 13180 |         { | 
 | 13181 |           li_config_table[k].flag_table[j] = 0; | 
 | 13182 |           li_config_table[j].flag_table[k] = 0; | 
 | 13183 |         } | 
 | 13184 |       } | 
 | 13185 |       mixer_calculate_coefs (a); | 
 | 13186 |       break; | 
 | 13187 |     } | 
 | 13188 |     if (plci->B1_facilities & B1_FACILITY_MIXER) | 
 | 13189 |     { | 
 | 13190 |       w = 0; | 
 | 13191 |       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length) | 
 | 13192 |         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); | 
 | 13193 |       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | 
 | 13194 |         w |= MIXER_FEATURE_ENABLE_TX_DATA; | 
 | 13195 |       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | 
 | 13196 |         w |= MIXER_FEATURE_ENABLE_RX_DATA; | 
 | 13197 |       *(p++) = (byte) w; | 
 | 13198 |       *(p++) = (byte)(w >> 8); | 
 | 13199 |       for (j = 0; j < sizeof(ch_map); j += 2) | 
 | 13200 |       { | 
 | 13201 |         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1)); | 
 | 13202 |         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id)); | 
 | 13203 |       } | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 13204 |       for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13205 |       { | 
 | 13206 |         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch]; | 
 | 13207 |         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch]; | 
 | 13208 |         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED) | 
 | 13209 |         { | 
 | 13210 |           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01); | 
 | 13211 |           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | 
 | 13212 |           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4; | 
 | 13213 |         } | 
 | 13214 |         else | 
 | 13215 |         { | 
 | 13216 |           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ? | 
 | 13217 |             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00; | 
 | 13218 |         } | 
 | 13219 |       } | 
 | 13220 |     } | 
 | 13221 |     else | 
 | 13222 |     { | 
 | 13223 |       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++) | 
 | 13224 |         *(p++) = a->adv_voice_coef_buffer[i]; | 
 | 13225 |     } | 
 | 13226 |   } | 
 | 13227 |   else | 
 | 13228 |  | 
 | 13229 |   { | 
 | 13230 |     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++) | 
 | 13231 |       *(p++) = a->adv_voice_coef_buffer[i]; | 
 | 13232 |   } | 
 | 13233 |   coef_buffer[0] = (p - coef_buffer) - 1; | 
 | 13234 |   add_p (plci, FTY, coef_buffer); | 
 | 13235 |   sig_req (plci, TEL_CTRL, 0); | 
 | 13236 |   send_req (plci); | 
 | 13237 | } | 
 | 13238 |  | 
 | 13239 |  | 
 | 13240 | static void adv_voice_clear_config (PLCI   *plci) | 
 | 13241 | { | 
 | 13242 |   DIVA_CAPI_ADAPTER   *a; | 
 | 13243 |  | 
 | 13244 |   word i, j; | 
 | 13245 |  | 
 | 13246 |  | 
 | 13247 |   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config", | 
 | 13248 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13249 |     (char   *)(FILE_), __LINE__)); | 
 | 13250 |  | 
 | 13251 |   a = plci->adapter; | 
 | 13252 |   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | 
 | 13253 |   { | 
 | 13254 |     a->adv_voice_coef_length = 0; | 
 | 13255 |  | 
 | 13256 |     if (!a->li_pri && (plci->li_bchannel_id != 0) | 
 | 13257 |      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 13258 |     { | 
 | 13259 |       i = a->li_base + (plci->li_bchannel_id - 1); | 
 | 13260 |       li_config_table[i].curchnl = 0; | 
 | 13261 |       li_config_table[i].channel = 0; | 
 | 13262 |       li_config_table[i].chflags = 0; | 
 | 13263 |       for (j = 0; j < li_total_channels; j++) | 
 | 13264 |       { | 
 | 13265 |         li_config_table[i].flag_table[j] = 0; | 
 | 13266 |         li_config_table[j].flag_table[i] = 0; | 
 | 13267 |         li_config_table[i].coef_table[j] = 0; | 
 | 13268 |         li_config_table[j].coef_table[i] = 0; | 
 | 13269 |       } | 
 | 13270 |       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET; | 
 | 13271 |       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | 
 | 13272 |       li_config_table[i].curchnl = 0; | 
 | 13273 |       li_config_table[i].channel = 0; | 
 | 13274 |       li_config_table[i].chflags = 0; | 
 | 13275 |       for (j = 0; j < li_total_channels; j++) | 
 | 13276 |       { | 
 | 13277 |         li_config_table[i].flag_table[j] = 0; | 
 | 13278 |         li_config_table[j].flag_table[i] = 0; | 
 | 13279 |         li_config_table[i].coef_table[j] = 0; | 
 | 13280 |         li_config_table[j].coef_table[i] = 0; | 
 | 13281 |       } | 
 | 13282 |       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | 
 | 13283 |       { | 
 | 13284 |         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | 
 | 13285 |         li_config_table[i].curchnl = 0; | 
 | 13286 |         li_config_table[i].channel = 0; | 
 | 13287 |         li_config_table[i].chflags = 0; | 
 | 13288 |         for (j = 0; j < li_total_channels; j++) | 
 | 13289 |         { | 
 | 13290 |           li_config_table[i].flag_table[j] = 0; | 
 | 13291 |           li_config_table[j].flag_table[i] = 0; | 
 | 13292 |           li_config_table[i].coef_table[j] = 0; | 
 | 13293 |           li_config_table[j].coef_table[i] = 0; | 
 | 13294 |         } | 
 | 13295 |       } | 
 | 13296 |     } | 
 | 13297 |  | 
 | 13298 |   } | 
 | 13299 | } | 
 | 13300 |  | 
 | 13301 |  | 
 | 13302 | static void adv_voice_prepare_switch (dword Id, PLCI   *plci) | 
 | 13303 | { | 
 | 13304 |  | 
 | 13305 |   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch", | 
 | 13306 |     UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 13307 |  | 
 | 13308 | } | 
 | 13309 |  | 
 | 13310 |  | 
 | 13311 | static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc) | 
 | 13312 | { | 
 | 13313 |  | 
 | 13314 |   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d", | 
 | 13315 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 13316 |  | 
 | 13317 |   return (GOOD); | 
 | 13318 | } | 
 | 13319 |  | 
 | 13320 |  | 
 | 13321 | static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc) | 
 | 13322 | { | 
 | 13323 |   DIVA_CAPI_ADAPTER   *a; | 
 | 13324 |   word Info; | 
 | 13325 |  | 
 | 13326 |   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d", | 
 | 13327 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 13328 |  | 
 | 13329 |   Info = GOOD; | 
 | 13330 |   a = plci->adapter; | 
 | 13331 |   if ((plci->B1_facilities & B1_FACILITY_VOICE) | 
 | 13332 |    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | 
 | 13333 |   { | 
 | 13334 |     switch (plci->adjust_b_state) | 
 | 13335 |     { | 
 | 13336 |     case ADJUST_B_RESTORE_VOICE_1: | 
 | 13337 |       plci->internal_command = plci->adjust_b_command; | 
 | 13338 |       if (plci->sig_req) | 
 | 13339 |       { | 
 | 13340 |         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1; | 
 | 13341 |         break; | 
 | 13342 |       } | 
 | 13343 |       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE); | 
 | 13344 |       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2; | 
 | 13345 |       break; | 
 | 13346 |     case ADJUST_B_RESTORE_VOICE_2: | 
 | 13347 |       if ((Rc != OK) && (Rc != OK_FC)) | 
 | 13348 |       { | 
 | 13349 |         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x", | 
 | 13350 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 13351 |         Info = _WRONG_STATE; | 
 | 13352 |         break; | 
 | 13353 |       } | 
 | 13354 |       break; | 
 | 13355 |     } | 
 | 13356 |   } | 
 | 13357 |   return (Info); | 
 | 13358 | } | 
 | 13359 |  | 
 | 13360 |  | 
 | 13361 |  | 
 | 13362 |  | 
 | 13363 | /*------------------------------------------------------------------*/ | 
 | 13364 | /* B1 resource switching                                            */ | 
 | 13365 | /*------------------------------------------------------------------*/ | 
 | 13366 |  | 
 | 13367 | static byte b1_facilities_table[] = | 
 | 13368 | { | 
 | 13369 |   0x00,  /* 0  No bchannel resources      */ | 
 | 13370 |   0x00,  /* 1  Codec (automatic law)      */ | 
 | 13371 |   0x00,  /* 2  Codec (A-law)              */ | 
 | 13372 |   0x00,  /* 3  Codec (y-law)              */ | 
 | 13373 |   0x00,  /* 4  HDLC for X.21              */ | 
 | 13374 |   0x00,  /* 5  HDLC                       */ | 
 | 13375 |   0x00,  /* 6  External Device 0          */ | 
 | 13376 |   0x00,  /* 7  External Device 1          */ | 
 | 13377 |   0x00,  /* 8  HDLC 56k                   */ | 
 | 13378 |   0x00,  /* 9  Transparent                */ | 
 | 13379 |   0x00,  /* 10 Loopback to network        */ | 
 | 13380 |   0x00,  /* 11 Test pattern to net        */ | 
 | 13381 |   0x00,  /* 12 Rate adaptation sync       */ | 
 | 13382 |   0x00,  /* 13 Rate adaptation async      */ | 
 | 13383 |   0x00,  /* 14 R-Interface                */ | 
 | 13384 |   0x00,  /* 15 HDLC 128k leased line      */ | 
 | 13385 |   0x00,  /* 16 FAX                        */ | 
 | 13386 |   0x00,  /* 17 Modem async                */ | 
 | 13387 |   0x00,  /* 18 Modem sync HDLC            */ | 
 | 13388 |   0x00,  /* 19 V.110 async HDLC           */ | 
 | 13389 |   0x12,  /* 20 Adv voice (Trans,mixer)    */ | 
 | 13390 |   0x00,  /* 21 Codec connected to IC      */ | 
 | 13391 |   0x0c,  /* 22 Trans,DTMF                 */ | 
 | 13392 |   0x1e,  /* 23 Trans,DTMF+mixer           */ | 
 | 13393 |   0x1f,  /* 24 Trans,DTMF+mixer+local     */ | 
 | 13394 |   0x13,  /* 25 Trans,mixer+local          */ | 
 | 13395 |   0x12,  /* 26 HDLC,mixer                 */ | 
 | 13396 |   0x12,  /* 27 HDLC 56k,mixer             */ | 
 | 13397 |   0x2c,  /* 28 Trans,LEC+DTMF             */ | 
 | 13398 |   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */ | 
 | 13399 |   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */ | 
 | 13400 |   0x2c,  /* 31 RTP,LEC+DTMF               */ | 
 | 13401 |   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */ | 
 | 13402 |   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */ | 
 | 13403 |   0x00,  /* 34 Signaling task             */ | 
 | 13404 |   0x00,  /* 35 PIAFS                      */ | 
 | 13405 |   0x0c,  /* 36 Trans,DTMF+TONE            */ | 
 | 13406 |   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */ | 
 | 13407 |   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/ | 
 | 13408 | }; | 
 | 13409 |  | 
 | 13410 |  | 
 | 13411 | static word get_b1_facilities (PLCI   * plci, byte b1_resource) | 
 | 13412 | { | 
 | 13413 |   word b1_facilities; | 
 | 13414 |  | 
 | 13415 |   b1_facilities = b1_facilities_table[b1_resource]; | 
 | 13416 |   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25)) | 
 | 13417 |   { | 
 | 13418 |  | 
 | 13419 |     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE)) | 
 | 13420 |        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE))))) | 
 | 13421 |  | 
 | 13422 |     { | 
 | 13423 |       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND) | 
 | 13424 |         b1_facilities |= B1_FACILITY_DTMFX; | 
 | 13425 |       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE) | 
 | 13426 |         b1_facilities |= B1_FACILITY_DTMFR; | 
 | 13427 |     } | 
 | 13428 |   } | 
 | 13429 |   if ((b1_resource == 17) || (b1_resource == 18)) | 
 | 13430 |   { | 
 | 13431 |     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN)) | 
 | 13432 |       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR; | 
 | 13433 |   } | 
 | 13434 | /* | 
 | 13435 |   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x", | 
 | 13436 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13437 |     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites)); | 
 | 13438 | */ | 
 | 13439 |   return (b1_facilities); | 
 | 13440 | } | 
 | 13441 |  | 
 | 13442 |  | 
 | 13443 | static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities) | 
 | 13444 | { | 
 | 13445 |   byte b; | 
 | 13446 |  | 
 | 13447 |   switch (b1_resource) | 
 | 13448 |   { | 
 | 13449 |   case 5: | 
 | 13450 |   case 26: | 
 | 13451 |     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | 
 | 13452 |       b = 26; | 
 | 13453 |     else | 
 | 13454 |       b = 5; | 
 | 13455 |     break; | 
 | 13456 |  | 
 | 13457 |   case 8: | 
 | 13458 |   case 27: | 
 | 13459 |     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | 
 | 13460 |       b = 27; | 
 | 13461 |     else | 
 | 13462 |       b = 8; | 
 | 13463 |     break; | 
 | 13464 |  | 
 | 13465 |   case 9: | 
 | 13466 |   case 20: | 
 | 13467 |   case 22: | 
 | 13468 |   case 23: | 
 | 13469 |   case 24: | 
 | 13470 |   case 25: | 
 | 13471 |   case 28: | 
 | 13472 |   case 29: | 
 | 13473 |   case 30: | 
 | 13474 |   case 36: | 
 | 13475 |   case 37: | 
 | 13476 |   case 38: | 
 | 13477 |     if (b1_facilities & B1_FACILITY_EC) | 
 | 13478 |     { | 
 | 13479 |       if (b1_facilities & B1_FACILITY_LOCAL) | 
 | 13480 |         b = 30; | 
 | 13481 |       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | 
 | 13482 |         b = 29; | 
 | 13483 |       else | 
 | 13484 |         b = 28; | 
 | 13485 |     } | 
 | 13486 |  | 
 | 13487 |     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER)) | 
 | 13488 |       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE)) | 
 | 13489 |        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE))))) | 
 | 13490 |     { | 
 | 13491 |       if (b1_facilities & B1_FACILITY_LOCAL) | 
 | 13492 |         b = 38; | 
 | 13493 |       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | 
 | 13494 |         b = 37; | 
 | 13495 |       else | 
 | 13496 |         b = 36; | 
 | 13497 |     } | 
 | 13498 |  | 
 | 13499 |     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF) | 
 | 13500 |       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)) | 
 | 13501 |      || ((b1_facilities & B1_FACILITY_DTMFR) | 
 | 13502 |       && ((b1_facilities & B1_FACILITY_MIXER) | 
 | 13503 |        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))) | 
 | 13504 |      || ((b1_facilities & B1_FACILITY_DTMFX) | 
 | 13505 |       && ((b1_facilities & B1_FACILITY_MIXER) | 
 | 13506 |        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)))) | 
 | 13507 |     { | 
 | 13508 |       if (b1_facilities & B1_FACILITY_LOCAL) | 
 | 13509 |         b = 24; | 
 | 13510 |       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | 
 | 13511 |         b = 23; | 
 | 13512 |       else | 
 | 13513 |         b = 22; | 
 | 13514 |     } | 
 | 13515 |     else | 
 | 13516 |     { | 
 | 13517 |       if (b1_facilities & B1_FACILITY_LOCAL) | 
 | 13518 |         b = 25; | 
 | 13519 |       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | 
 | 13520 |         b = 20; | 
 | 13521 |       else | 
 | 13522 |         b = 9; | 
 | 13523 |     } | 
 | 13524 |     break; | 
 | 13525 |  | 
 | 13526 |   case 31: | 
 | 13527 |   case 32: | 
 | 13528 |   case 33: | 
 | 13529 |     if (b1_facilities & B1_FACILITY_LOCAL) | 
 | 13530 |       b = 33; | 
 | 13531 |     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | 
 | 13532 |       b = 32; | 
 | 13533 |     else | 
 | 13534 |       b = 31; | 
 | 13535 |     break; | 
 | 13536 |  | 
 | 13537 |   default: | 
 | 13538 |     b = b1_resource; | 
 | 13539 |   } | 
 | 13540 |   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x", | 
 | 13541 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13542 |     (char   *)(FILE_), __LINE__, | 
 | 13543 |     b1_resource, b1_facilities, b, get_b1_facilities (plci, b))); | 
 | 13544 |   return (b); | 
 | 13545 | } | 
 | 13546 |  | 
 | 13547 |  | 
 | 13548 | static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities) | 
 | 13549 | { | 
 | 13550 |   word removed_facilities; | 
 | 13551 |  | 
 | 13552 |   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x", | 
 | 13553 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13554 |     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities, | 
 | 13555 |     new_b1_facilities & get_b1_facilities (plci, new_b1_resource))); | 
 | 13556 |  | 
 | 13557 |   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource); | 
 | 13558 |   removed_facilities = plci->B1_facilities & ~new_b1_facilities; | 
 | 13559 |  | 
 | 13560 |   if (removed_facilities & B1_FACILITY_EC) | 
 | 13561 |     ec_clear_config (plci); | 
 | 13562 |  | 
 | 13563 |  | 
 | 13564 |   if (removed_facilities & B1_FACILITY_DTMFR) | 
 | 13565 |   { | 
 | 13566 |     dtmf_rec_clear_config (plci); | 
 | 13567 |     dtmf_parameter_clear_config (plci); | 
 | 13568 |   } | 
 | 13569 |   if (removed_facilities & B1_FACILITY_DTMFX) | 
 | 13570 |     dtmf_send_clear_config (plci); | 
 | 13571 |  | 
 | 13572 |  | 
 | 13573 |   if (removed_facilities & B1_FACILITY_MIXER) | 
 | 13574 |     mixer_clear_config (plci); | 
 | 13575 |  | 
 | 13576 |   if (removed_facilities & B1_FACILITY_VOICE) | 
 | 13577 |     adv_voice_clear_config (plci); | 
 | 13578 |   plci->B1_facilities = new_b1_facilities; | 
 | 13579 | } | 
 | 13580 |  | 
 | 13581 |  | 
 | 13582 | static void adjust_b_clear (PLCI   *plci) | 
 | 13583 | { | 
 | 13584 |  | 
 | 13585 |   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear", | 
 | 13586 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 13587 |     (char   *)(FILE_), __LINE__)); | 
 | 13588 |  | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 13589 |   plci->adjust_b_restore = false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13590 | } | 
 | 13591 |  | 
 | 13592 |  | 
 | 13593 | static word adjust_b_process (dword Id, PLCI   *plci, byte Rc) | 
 | 13594 | { | 
 | 13595 |   word Info; | 
 | 13596 |   byte b1_resource; | 
 | 13597 |   NCCI   * ncci_ptr; | 
 | 13598 |     API_PARSE bp[2]; | 
 | 13599 |  | 
 | 13600 |   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d", | 
 | 13601 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | 
 | 13602 |  | 
 | 13603 |   Info = GOOD; | 
 | 13604 |   switch (plci->adjust_b_state) | 
 | 13605 |   { | 
 | 13606 |   case ADJUST_B_START: | 
 | 13607 |     if ((plci->adjust_b_parms_msg == NULL) | 
 | 13608 |      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1) | 
 | 13609 |      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | | 
 | 13610 |       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0)) | 
 | 13611 |     { | 
 | 13612 |       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ? | 
 | 13613 |         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities); | 
 | 13614 |       if (b1_resource == plci->B1_resource) | 
 | 13615 |       { | 
 | 13616 |         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities); | 
 | 13617 |         break; | 
 | 13618 |       } | 
 | 13619 |       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource)) | 
 | 13620 |       { | 
 | 13621 |         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x", | 
 | 13622 |           UnMapId (Id), (char   *)(FILE_), __LINE__, | 
 | 13623 |           plci->B1_resource, b1_resource, plci->adjust_b_facilities)); | 
 | 13624 |         Info = _WRONG_STATE; | 
 | 13625 |         break; | 
 | 13626 |       } | 
 | 13627 |     } | 
 | 13628 |     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | 
 | 13629 |     { | 
 | 13630 |  | 
 | 13631 |       mixer_prepare_switch (Id, plci); | 
 | 13632 |  | 
 | 13633 |  | 
 | 13634 |       dtmf_prepare_switch (Id, plci); | 
 | 13635 |       dtmf_parameter_prepare_switch (Id, plci); | 
 | 13636 |  | 
 | 13637 |  | 
 | 13638 |       ec_prepare_switch (Id, plci); | 
 | 13639 |  | 
 | 13640 |       adv_voice_prepare_switch (Id, plci); | 
 | 13641 |     } | 
 | 13642 |     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1; | 
 | 13643 |     Rc = OK; | 
 | 13644 |   case ADJUST_B_SAVE_MIXER_1: | 
 | 13645 |     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | 
 | 13646 |     { | 
 | 13647 |  | 
 | 13648 |       Info = mixer_save_config (Id, plci, Rc); | 
 | 13649 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13650 |         break; | 
 | 13651 |  | 
 | 13652 |     } | 
 | 13653 |     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1; | 
 | 13654 |     Rc = OK; | 
 | 13655 |   case ADJUST_B_SAVE_DTMF_1: | 
 | 13656 |     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | 
 | 13657 |     { | 
 | 13658 |  | 
 | 13659 |       Info = dtmf_save_config (Id, plci, Rc); | 
 | 13660 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13661 |         break; | 
 | 13662 |  | 
 | 13663 |     } | 
 | 13664 |     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1; | 
 | 13665 |   case ADJUST_B_REMOVE_L23_1: | 
 | 13666 |     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23) | 
 | 13667 |      && plci->NL.Id && !plci->nl_remove_id) | 
 | 13668 |     { | 
 | 13669 |       plci->internal_command = plci->adjust_b_command; | 
 | 13670 |       if (plci->adjust_b_ncci != 0) | 
 | 13671 |       { | 
 | 13672 |         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]); | 
 | 13673 |         while (ncci_ptr->data_pending) | 
 | 13674 |         { | 
 | 13675 |           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P; | 
 | 13676 |           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]); | 
 | 13677 |         } | 
 | 13678 |         while (ncci_ptr->data_ack_pending) | 
 | 13679 |           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]); | 
 | 13680 |       } | 
 | 13681 |       nl_req_ncci (plci, REMOVE, | 
 | 13682 |         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0)); | 
 | 13683 |       send_req (plci); | 
 | 13684 |       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2; | 
 | 13685 |       break; | 
 | 13686 |     } | 
 | 13687 |     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2; | 
 | 13688 |     Rc = OK; | 
 | 13689 |   case ADJUST_B_REMOVE_L23_2: | 
 | 13690 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 13691 |     { | 
 | 13692 |       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x", | 
 | 13693 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 13694 |       Info = _WRONG_STATE; | 
 | 13695 |       break; | 
 | 13696 |     } | 
 | 13697 |     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23) | 
 | 13698 |     { | 
 | 13699 |       if (plci_nl_busy (plci)) | 
 | 13700 |       { | 
 | 13701 |         plci->internal_command = plci->adjust_b_command; | 
 | 13702 |         break; | 
 | 13703 |       } | 
 | 13704 |     } | 
 | 13705 |     plci->adjust_b_state = ADJUST_B_SAVE_EC_1; | 
 | 13706 |     Rc = OK; | 
 | 13707 |   case ADJUST_B_SAVE_EC_1: | 
 | 13708 |     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | 
 | 13709 |     { | 
 | 13710 |  | 
 | 13711 |       Info = ec_save_config (Id, plci, Rc); | 
 | 13712 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13713 |         break; | 
 | 13714 |  | 
 | 13715 |     } | 
 | 13716 |     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1; | 
 | 13717 |     Rc = OK; | 
 | 13718 |   case ADJUST_B_SAVE_DTMF_PARAMETER_1: | 
 | 13719 |     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | 
 | 13720 |     { | 
 | 13721 |  | 
 | 13722 |       Info = dtmf_parameter_save_config (Id, plci, Rc); | 
 | 13723 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13724 |         break; | 
 | 13725 |  | 
 | 13726 |     } | 
 | 13727 |     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1; | 
 | 13728 |     Rc = OK; | 
 | 13729 |   case ADJUST_B_SAVE_VOICE_1: | 
 | 13730 |     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | 
 | 13731 |     { | 
 | 13732 |       Info = adv_voice_save_config (Id, plci, Rc); | 
 | 13733 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13734 |         break; | 
 | 13735 |     } | 
 | 13736 |     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1; | 
 | 13737 |   case ADJUST_B_SWITCH_L1_1: | 
 | 13738 |     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1) | 
 | 13739 |     { | 
 | 13740 |       if (plci->sig_req) | 
 | 13741 |       { | 
 | 13742 |         plci->internal_command = plci->adjust_b_command; | 
 | 13743 |         break; | 
 | 13744 |       } | 
 | 13745 |       if (plci->adjust_b_parms_msg != NULL) | 
 | 13746 |         api_load_msg (plci->adjust_b_parms_msg, bp); | 
 | 13747 |       else | 
 | 13748 |         api_load_msg (&plci->B_protocol, bp); | 
 | 13749 |       Info = add_b1 (plci, bp, | 
 | 13750 |         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0), | 
 | 13751 |         plci->adjust_b_facilities); | 
 | 13752 |       if (Info != GOOD) | 
 | 13753 |       { | 
 | 13754 |         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x", | 
 | 13755 |           UnMapId (Id), (char   *)(FILE_), __LINE__, | 
 | 13756 |           plci->B1_resource, plci->adjust_b_facilities)); | 
 | 13757 |         break; | 
 | 13758 |       } | 
 | 13759 |       plci->internal_command = plci->adjust_b_command; | 
 | 13760 |       sig_req (plci, RESOURCES, 0); | 
 | 13761 |       send_req (plci); | 
 | 13762 |       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2; | 
 | 13763 |       break; | 
 | 13764 |     } | 
 | 13765 |     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2; | 
 | 13766 |     Rc = OK; | 
 | 13767 |   case ADJUST_B_SWITCH_L1_2: | 
 | 13768 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 13769 |     { | 
 | 13770 |       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x", | 
 | 13771 |         UnMapId (Id), (char   *)(FILE_), __LINE__, | 
 | 13772 |         Rc, plci->B1_resource, plci->adjust_b_facilities)); | 
 | 13773 |       Info = _WRONG_STATE; | 
 | 13774 |       break; | 
 | 13775 |     } | 
 | 13776 |     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1; | 
 | 13777 |     Rc = OK; | 
 | 13778 |   case ADJUST_B_RESTORE_VOICE_1: | 
 | 13779 |   case ADJUST_B_RESTORE_VOICE_2: | 
 | 13780 |     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | 
 | 13781 |     { | 
 | 13782 |       Info = adv_voice_restore_config (Id, plci, Rc); | 
 | 13783 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13784 |         break; | 
 | 13785 |     } | 
 | 13786 |     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1; | 
 | 13787 |     Rc = OK; | 
 | 13788 |   case ADJUST_B_RESTORE_DTMF_PARAMETER_1: | 
 | 13789 |   case ADJUST_B_RESTORE_DTMF_PARAMETER_2: | 
 | 13790 |     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | 
 | 13791 |     { | 
 | 13792 |  | 
 | 13793 |       Info = dtmf_parameter_restore_config (Id, plci, Rc); | 
 | 13794 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13795 |         break; | 
 | 13796 |  | 
 | 13797 |     } | 
 | 13798 |     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1; | 
 | 13799 |     Rc = OK; | 
 | 13800 |   case ADJUST_B_RESTORE_EC_1: | 
 | 13801 |   case ADJUST_B_RESTORE_EC_2: | 
 | 13802 |     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | 
 | 13803 |     { | 
 | 13804 |  | 
 | 13805 |       Info = ec_restore_config (Id, plci, Rc); | 
 | 13806 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13807 |         break; | 
 | 13808 |  | 
 | 13809 |     } | 
 | 13810 |     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1; | 
 | 13811 |   case ADJUST_B_ASSIGN_L23_1: | 
 | 13812 |     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23) | 
 | 13813 |     { | 
 | 13814 |       if (plci_nl_busy (plci)) | 
 | 13815 |       { | 
 | 13816 |         plci->internal_command = plci->adjust_b_command; | 
 | 13817 |         break; | 
 | 13818 |       } | 
 | 13819 |       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) | 
 | 13820 |         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; | 
 | 13821 |       if (plci->adjust_b_parms_msg != NULL) | 
 | 13822 |         api_load_msg (plci->adjust_b_parms_msg, bp); | 
 | 13823 |       else | 
 | 13824 |         api_load_msg (&plci->B_protocol, bp); | 
 | 13825 |       Info = add_b23 (plci, bp); | 
 | 13826 |       if (Info != GOOD) | 
 | 13827 |       { | 
 | 13828 |         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x", | 
 | 13829 |           UnMapId (Id), (char   *)(FILE_), __LINE__, Info)); | 
 | 13830 |         break; | 
 | 13831 |       } | 
 | 13832 |       plci->internal_command = plci->adjust_b_command; | 
 | 13833 |       nl_req_ncci (plci, ASSIGN, 0); | 
 | 13834 |       send_req (plci); | 
 | 13835 |       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2; | 
 | 13836 |       break; | 
 | 13837 |     } | 
 | 13838 |     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2; | 
 | 13839 |     Rc = ASSIGN_OK; | 
 | 13840 |   case ADJUST_B_ASSIGN_L23_2: | 
 | 13841 |     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK)) | 
 | 13842 |     { | 
 | 13843 |       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x", | 
 | 13844 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 13845 |       Info = _WRONG_STATE; | 
 | 13846 |       break; | 
 | 13847 |     } | 
 | 13848 |     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23) | 
 | 13849 |     { | 
 | 13850 |       if (Rc != ASSIGN_OK) | 
 | 13851 |       { | 
 | 13852 |         plci->internal_command = plci->adjust_b_command; | 
 | 13853 |         break; | 
 | 13854 |       } | 
 | 13855 |     } | 
 | 13856 |     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT) | 
 | 13857 |     { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 13858 |       plci->adjust_b_restore = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13859 |       break; | 
 | 13860 |     } | 
 | 13861 |     plci->adjust_b_state = ADJUST_B_CONNECT_1; | 
 | 13862 |   case ADJUST_B_CONNECT_1: | 
 | 13863 |     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) | 
 | 13864 |     { | 
 | 13865 |       plci->internal_command = plci->adjust_b_command; | 
 | 13866 |       if (plci_nl_busy (plci)) | 
 | 13867 |         break; | 
 | 13868 |       nl_req_ncci (plci, N_CONNECT, 0); | 
 | 13869 |       send_req (plci); | 
 | 13870 |       plci->adjust_b_state = ADJUST_B_CONNECT_2; | 
 | 13871 |       break; | 
 | 13872 |     } | 
 | 13873 |     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | 
 | 13874 |     Rc = OK; | 
 | 13875 |   case ADJUST_B_CONNECT_2: | 
 | 13876 |   case ADJUST_B_CONNECT_3: | 
 | 13877 |   case ADJUST_B_CONNECT_4: | 
 | 13878 |     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0)) | 
 | 13879 |     { | 
 | 13880 |       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x", | 
 | 13881 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 13882 |       Info = _WRONG_STATE; | 
 | 13883 |       break; | 
 | 13884 |     } | 
 | 13885 |     if (Rc == OK) | 
 | 13886 |     { | 
 | 13887 |       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) | 
 | 13888 |       { | 
 | 13889 |         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci); | 
 | 13890 |         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16); | 
 | 13891 |       } | 
 | 13892 |       if (plci->adjust_b_state == ADJUST_B_CONNECT_2) | 
 | 13893 |         plci->adjust_b_state = ADJUST_B_CONNECT_3; | 
 | 13894 |       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4) | 
 | 13895 |         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | 
 | 13896 |     } | 
 | 13897 |     else if (Rc == 0) | 
 | 13898 |     { | 
 | 13899 |       if (plci->adjust_b_state == ADJUST_B_CONNECT_2) | 
 | 13900 |         plci->adjust_b_state = ADJUST_B_CONNECT_4; | 
 | 13901 |       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3) | 
 | 13902 |         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | 
 | 13903 |     } | 
 | 13904 |     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1) | 
 | 13905 |     { | 
 | 13906 |       plci->internal_command = plci->adjust_b_command; | 
 | 13907 |       break; | 
 | 13908 |     } | 
 | 13909 |     Rc = OK; | 
 | 13910 |   case ADJUST_B_RESTORE_DTMF_1: | 
 | 13911 |   case ADJUST_B_RESTORE_DTMF_2: | 
 | 13912 |     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | 
 | 13913 |     { | 
 | 13914 |  | 
 | 13915 |       Info = dtmf_restore_config (Id, plci, Rc); | 
 | 13916 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13917 |         break; | 
 | 13918 |  | 
 | 13919 |     } | 
 | 13920 |     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1; | 
 | 13921 |     Rc = OK; | 
 | 13922 |   case ADJUST_B_RESTORE_MIXER_1: | 
 | 13923 |   case ADJUST_B_RESTORE_MIXER_2: | 
 | 13924 |   case ADJUST_B_RESTORE_MIXER_3: | 
 | 13925 |   case ADJUST_B_RESTORE_MIXER_4: | 
 | 13926 |   case ADJUST_B_RESTORE_MIXER_5: | 
 | 13927 |   case ADJUST_B_RESTORE_MIXER_6: | 
 | 13928 |   case ADJUST_B_RESTORE_MIXER_7: | 
 | 13929 |     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | 
 | 13930 |     { | 
 | 13931 |  | 
 | 13932 |       Info = mixer_restore_config (Id, plci, Rc); | 
 | 13933 |       if ((Info != GOOD) || plci->internal_command) | 
 | 13934 |         break; | 
 | 13935 |  | 
 | 13936 |     } | 
 | 13937 |     plci->adjust_b_state = ADJUST_B_END; | 
 | 13938 |   case ADJUST_B_END: | 
 | 13939 |     break; | 
 | 13940 |   } | 
 | 13941 |   return (Info); | 
 | 13942 | } | 
 | 13943 |  | 
 | 13944 |  | 
 | 13945 | static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command) | 
 | 13946 | { | 
 | 13947 |  | 
 | 13948 |   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x", | 
 | 13949 |     UnMapId (Id), (char   *)(FILE_), __LINE__, | 
 | 13950 |     plci->B1_resource, b1_facilities)); | 
 | 13951 |  | 
 | 13952 |   plci->adjust_b_parms_msg = bp_msg; | 
 | 13953 |   plci->adjust_b_facilities = b1_facilities; | 
 | 13954 |   plci->adjust_b_command = internal_command; | 
 | 13955 |   plci->adjust_b_ncci = (word)(Id >> 16); | 
 | 13956 |   if ((bp_msg == NULL) && (plci->B1_resource == 0)) | 
 | 13957 |     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1; | 
 | 13958 |   else | 
 | 13959 |     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE; | 
 | 13960 |   plci->adjust_b_state = ADJUST_B_START; | 
 | 13961 |   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...", | 
 | 13962 |     UnMapId (Id), (char   *)(FILE_), __LINE__, | 
 | 13963 |     plci->B1_resource, b1_facilities)); | 
 | 13964 | } | 
 | 13965 |  | 
 | 13966 |  | 
 | 13967 | static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc) | 
 | 13968 | { | 
 | 13969 |   word internal_command; | 
 | 13970 |  | 
 | 13971 |   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x", | 
 | 13972 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 13973 |  | 
 | 13974 |   internal_command = plci->internal_command; | 
 | 13975 |   plci->internal_command = 0; | 
 | 13976 |   switch (internal_command) | 
 | 13977 |   { | 
 | 13978 |   default: | 
 | 13979 |     plci->command = 0; | 
 | 13980 |     if (plci->req_in != 0) | 
 | 13981 |     { | 
 | 13982 |       plci->internal_command = ADJUST_B_RESTORE_1; | 
 | 13983 |       break; | 
 | 13984 |     } | 
 | 13985 |     Rc = OK; | 
 | 13986 |   case ADJUST_B_RESTORE_1: | 
 | 13987 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 13988 |     { | 
 | 13989 |       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x", | 
 | 13990 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 13991 |     } | 
 | 13992 |     plci->adjust_b_parms_msg = NULL; | 
 | 13993 |     plci->adjust_b_facilities = plci->B1_facilities; | 
 | 13994 |     plci->adjust_b_command = ADJUST_B_RESTORE_2; | 
 | 13995 |     plci->adjust_b_ncci = (word)(Id >> 16); | 
 | 13996 |     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE; | 
 | 13997 |     plci->adjust_b_state = ADJUST_B_START; | 
 | 13998 |     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...", | 
 | 13999 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14000 |   case ADJUST_B_RESTORE_2: | 
 | 14001 |     if (adjust_b_process (Id, plci, Rc) != GOOD) | 
 | 14002 |     { | 
 | 14003 |       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed", | 
 | 14004 |         UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14005 |     } | 
 | 14006 |     if (plci->internal_command) | 
 | 14007 |       break; | 
 | 14008 |     break; | 
 | 14009 |   } | 
 | 14010 | } | 
 | 14011 |  | 
 | 14012 |  | 
 | 14013 | static void reset_b3_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14014 | { | 
 | 14015 |   word Info; | 
 | 14016 |   word internal_command; | 
 | 14017 |  | 
 | 14018 |   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x", | 
 | 14019 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14020 |  | 
 | 14021 |   Info = GOOD; | 
 | 14022 |   internal_command = plci->internal_command; | 
 | 14023 |   plci->internal_command = 0; | 
 | 14024 |   switch (internal_command) | 
 | 14025 |   { | 
 | 14026 |   default: | 
 | 14027 |     plci->command = 0; | 
 | 14028 |     plci->adjust_b_parms_msg = NULL; | 
 | 14029 |     plci->adjust_b_facilities = plci->B1_facilities; | 
 | 14030 |     plci->adjust_b_command = RESET_B3_COMMAND_1; | 
 | 14031 |     plci->adjust_b_ncci = (word)(Id >> 16); | 
 | 14032 |     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT; | 
 | 14033 |     plci->adjust_b_state = ADJUST_B_START; | 
 | 14034 |     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...", | 
 | 14035 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14036 |   case RESET_B3_COMMAND_1: | 
 | 14037 |     Info = adjust_b_process (Id, plci, Rc); | 
 | 14038 |     if (Info != GOOD) | 
 | 14039 |     { | 
 | 14040 |       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed", | 
 | 14041 |         UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14042 |       break; | 
 | 14043 |     } | 
 | 14044 |     if (plci->internal_command) | 
 | 14045 |       return; | 
 | 14046 |     break; | 
 | 14047 |   } | 
 | 14048 | /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/ | 
 | 14049 |   sendf(plci->appl,_RESET_B3_I,Id,0,"s",""); | 
 | 14050 | } | 
 | 14051 |  | 
 | 14052 |  | 
 | 14053 | static void select_b_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14054 | { | 
 | 14055 |   word Info; | 
 | 14056 |   word internal_command; | 
 | 14057 |   byte esc_chi[3]; | 
 | 14058 |  | 
 | 14059 |   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x", | 
 | 14060 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14061 |  | 
 | 14062 |   Info = GOOD; | 
 | 14063 |   internal_command = plci->internal_command; | 
 | 14064 |   plci->internal_command = 0; | 
 | 14065 |   switch (internal_command) | 
 | 14066 |   { | 
 | 14067 |   default: | 
 | 14068 |     plci->command = 0; | 
 | 14069 |     plci->adjust_b_parms_msg = &plci->saved_msg; | 
 | 14070 |     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI)) | 
 | 14071 |       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE; | 
 | 14072 |     else | 
 | 14073 |       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE; | 
 | 14074 |     plci->adjust_b_command = SELECT_B_COMMAND_1; | 
 | 14075 |     plci->adjust_b_ncci = (word)(Id >> 16); | 
 | 14076 |     if (plci->saved_msg.parms[0].length == 0) | 
 | 14077 |     { | 
 | 14078 |       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 | | 
 | 14079 |         ADJUST_B_MODE_NO_RESOURCE; | 
 | 14080 |     } | 
 | 14081 |     else | 
 | 14082 |     { | 
 | 14083 |       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 | | 
 | 14084 |         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE; | 
 | 14085 |     } | 
 | 14086 |     plci->adjust_b_state = ADJUST_B_START; | 
 | 14087 |     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...", | 
 | 14088 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14089 |   case SELECT_B_COMMAND_1: | 
 | 14090 |     Info = adjust_b_process (Id, plci, Rc); | 
 | 14091 |     if (Info != GOOD) | 
 | 14092 |     { | 
 | 14093 |       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed", | 
 | 14094 |         UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14095 |       break; | 
 | 14096 |     } | 
 | 14097 |     if (plci->internal_command) | 
 | 14098 |       return; | 
 | 14099 |     if (plci->tel == ADV_VOICE) | 
 | 14100 |     { | 
 | 14101 |       esc_chi[0] = 0x02; | 
 | 14102 |       esc_chi[1] = 0x18; | 
 | 14103 |       esc_chi[2] = plci->b_channel; | 
 | 14104 |       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter); | 
 | 14105 |     } | 
 | 14106 |     break; | 
 | 14107 |   } | 
 | 14108 |   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info); | 
 | 14109 | } | 
 | 14110 |  | 
 | 14111 |  | 
 | 14112 | static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14113 | { | 
 | 14114 |   word Info; | 
 | 14115 |   word internal_command; | 
 | 14116 |  | 
 | 14117 |   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x", | 
 | 14118 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14119 |  | 
 | 14120 |   Info = GOOD; | 
 | 14121 |   internal_command = plci->internal_command; | 
 | 14122 |   plci->internal_command = 0; | 
 | 14123 |   switch (internal_command) | 
 | 14124 |   { | 
 | 14125 |   default: | 
 | 14126 |     plci->command = 0; | 
 | 14127 |   case FAX_CONNECT_ACK_COMMAND_1: | 
 | 14128 |     if (plci_nl_busy (plci)) | 
 | 14129 |     { | 
 | 14130 |       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1; | 
 | 14131 |       return; | 
 | 14132 |     } | 
 | 14133 |     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2; | 
 | 14134 |     plci->NData[0].P = plci->fax_connect_info_buffer; | 
 | 14135 |     plci->NData[0].PLength = plci->fax_connect_info_length; | 
 | 14136 |     plci->NL.X = plci->NData; | 
 | 14137 |     plci->NL.ReqCh = 0; | 
 | 14138 |     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK; | 
 | 14139 |     plci->adapter->request (&plci->NL); | 
 | 14140 |     return; | 
 | 14141 |   case FAX_CONNECT_ACK_COMMAND_2: | 
 | 14142 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 14143 |     { | 
 | 14144 |       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x", | 
 | 14145 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 14146 |       break; | 
 | 14147 |     } | 
 | 14148 |   } | 
 | 14149 |   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | 
 | 14150 |    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | 
 | 14151 |   { | 
 | 14152 |     if (plci->B3_prot == 4) | 
 | 14153 |       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | 
 | 14154 |     else | 
 | 14155 |       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | 
 | 14156 |     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | 
 | 14157 |   } | 
 | 14158 | } | 
 | 14159 |  | 
 | 14160 |  | 
 | 14161 | static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14162 | { | 
 | 14163 |   word Info; | 
 | 14164 |   word internal_command; | 
 | 14165 |  | 
 | 14166 |   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x", | 
 | 14167 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14168 |  | 
 | 14169 |   Info = GOOD; | 
 | 14170 |   internal_command = plci->internal_command; | 
 | 14171 |   plci->internal_command = 0; | 
 | 14172 |   switch (internal_command) | 
 | 14173 |   { | 
 | 14174 |   default: | 
 | 14175 |     plci->command = 0; | 
 | 14176 |   case FAX_EDATA_ACK_COMMAND_1: | 
 | 14177 |     if (plci_nl_busy (plci)) | 
 | 14178 |     { | 
 | 14179 |       plci->internal_command = FAX_EDATA_ACK_COMMAND_1; | 
 | 14180 |       return; | 
 | 14181 |     } | 
 | 14182 |     plci->internal_command = FAX_EDATA_ACK_COMMAND_2; | 
 | 14183 |     plci->NData[0].P = plci->fax_connect_info_buffer; | 
 | 14184 |     plci->NData[0].PLength = plci->fax_edata_ack_length; | 
 | 14185 |     plci->NL.X = plci->NData; | 
 | 14186 |     plci->NL.ReqCh = 0; | 
 | 14187 |     plci->NL.Req = plci->nl_req = (byte) N_EDATA; | 
 | 14188 |     plci->adapter->request (&plci->NL); | 
 | 14189 |     return; | 
 | 14190 |   case FAX_EDATA_ACK_COMMAND_2: | 
 | 14191 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 14192 |     { | 
 | 14193 |       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x", | 
 | 14194 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 14195 |       break; | 
 | 14196 |     } | 
 | 14197 |   } | 
 | 14198 | } | 
 | 14199 |  | 
 | 14200 |  | 
 | 14201 | static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14202 | { | 
 | 14203 |   word Info; | 
 | 14204 |   word internal_command; | 
 | 14205 |  | 
 | 14206 |   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x", | 
 | 14207 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14208 |  | 
 | 14209 |   Info = GOOD; | 
 | 14210 |   internal_command = plci->internal_command; | 
 | 14211 |   plci->internal_command = 0; | 
 | 14212 |   switch (internal_command) | 
 | 14213 |   { | 
 | 14214 |   default: | 
 | 14215 |     plci->command = 0; | 
 | 14216 |   case FAX_CONNECT_INFO_COMMAND_1: | 
 | 14217 |     if (plci_nl_busy (plci)) | 
 | 14218 |     { | 
 | 14219 |       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1; | 
 | 14220 |       return; | 
 | 14221 |     } | 
 | 14222 |     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2; | 
 | 14223 |     plci->NData[0].P = plci->fax_connect_info_buffer; | 
 | 14224 |     plci->NData[0].PLength = plci->fax_connect_info_length; | 
 | 14225 |     plci->NL.X = plci->NData; | 
 | 14226 |     plci->NL.ReqCh = 0; | 
 | 14227 |     plci->NL.Req = plci->nl_req = (byte) N_EDATA; | 
 | 14228 |     plci->adapter->request (&plci->NL); | 
 | 14229 |     return; | 
 | 14230 |   case FAX_CONNECT_INFO_COMMAND_2: | 
 | 14231 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 14232 |     { | 
 | 14233 |       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x", | 
 | 14234 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 14235 |       Info = _WRONG_STATE; | 
 | 14236 |       break; | 
 | 14237 |     } | 
 | 14238 |     if (plci_nl_busy (plci)) | 
 | 14239 |     { | 
 | 14240 |       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2; | 
 | 14241 |       return; | 
 | 14242 |     } | 
 | 14243 |     plci->command = _CONNECT_B3_R; | 
 | 14244 |     nl_req_ncci (plci, N_CONNECT, 0); | 
 | 14245 |     send_req (plci); | 
 | 14246 |     return; | 
 | 14247 |   } | 
 | 14248 |   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info); | 
 | 14249 | } | 
 | 14250 |  | 
 | 14251 |  | 
 | 14252 | static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14253 | { | 
 | 14254 |   word Info; | 
 | 14255 |   word internal_command; | 
 | 14256 |  | 
 | 14257 |   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x", | 
 | 14258 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14259 |  | 
 | 14260 |   Info = GOOD; | 
 | 14261 |   internal_command = plci->internal_command; | 
 | 14262 |   plci->internal_command = 0; | 
 | 14263 |   switch (internal_command) | 
 | 14264 |   { | 
 | 14265 |   default: | 
 | 14266 |     plci->command = 0; | 
 | 14267 |     plci->adjust_b_parms_msg = NULL; | 
 | 14268 |     plci->adjust_b_facilities = plci->B1_facilities; | 
 | 14269 |     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1; | 
 | 14270 |     plci->adjust_b_ncci = (word)(Id >> 16); | 
 | 14271 |     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23; | 
 | 14272 |     plci->adjust_b_state = ADJUST_B_START; | 
 | 14273 |     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...", | 
 | 14274 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14275 |   case FAX_ADJUST_B23_COMMAND_1: | 
 | 14276 |     Info = adjust_b_process (Id, plci, Rc); | 
 | 14277 |     if (Info != GOOD) | 
 | 14278 |     { | 
 | 14279 |       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed", | 
 | 14280 |         UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14281 |       break; | 
 | 14282 |     } | 
 | 14283 |     if (plci->internal_command) | 
 | 14284 |       return; | 
 | 14285 |   case FAX_ADJUST_B23_COMMAND_2: | 
 | 14286 |     if (plci_nl_busy (plci)) | 
 | 14287 |     { | 
 | 14288 |       plci->internal_command = FAX_ADJUST_B23_COMMAND_2; | 
 | 14289 |       return; | 
 | 14290 |     } | 
 | 14291 |     plci->command = _CONNECT_B3_R; | 
 | 14292 |     nl_req_ncci (plci, N_CONNECT, 0); | 
 | 14293 |     send_req (plci); | 
 | 14294 |     return; | 
 | 14295 |   } | 
 | 14296 |   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info); | 
 | 14297 | } | 
 | 14298 |  | 
 | 14299 |  | 
 | 14300 | static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14301 | { | 
 | 14302 |   word internal_command; | 
 | 14303 |  | 
 | 14304 |   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x", | 
 | 14305 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14306 |  | 
 | 14307 |   internal_command = plci->internal_command; | 
 | 14308 |   plci->internal_command = 0; | 
 | 14309 |   switch (internal_command) | 
 | 14310 |   { | 
 | 14311 |   default: | 
 | 14312 |     plci->command = 0; | 
 | 14313 |     plci->internal_command = FAX_DISCONNECT_COMMAND_1; | 
 | 14314 |     return; | 
 | 14315 |   case FAX_DISCONNECT_COMMAND_1: | 
 | 14316 |   case FAX_DISCONNECT_COMMAND_2: | 
 | 14317 |   case FAX_DISCONNECT_COMMAND_3: | 
 | 14318 |     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0)) | 
 | 14319 |     { | 
 | 14320 |       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x", | 
 | 14321 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 14322 |       break; | 
 | 14323 |     } | 
 | 14324 |     if (Rc == OK) | 
 | 14325 |     { | 
 | 14326 |       if ((internal_command == FAX_DISCONNECT_COMMAND_1) | 
 | 14327 |        || (internal_command == FAX_DISCONNECT_COMMAND_2)) | 
 | 14328 |       { | 
 | 14329 |         plci->internal_command = FAX_DISCONNECT_COMMAND_2; | 
 | 14330 |       } | 
 | 14331 |     } | 
 | 14332 |     else if (Rc == 0) | 
 | 14333 |     { | 
 | 14334 |       if (internal_command == FAX_DISCONNECT_COMMAND_1) | 
 | 14335 |         plci->internal_command = FAX_DISCONNECT_COMMAND_3; | 
 | 14336 |     } | 
 | 14337 |     return; | 
 | 14338 |   } | 
 | 14339 | } | 
 | 14340 |  | 
 | 14341 |  | 
 | 14342 |  | 
 | 14343 | static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14344 | { | 
 | 14345 |   word Info; | 
 | 14346 |   word internal_command; | 
 | 14347 |  | 
 | 14348 |   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x", | 
 | 14349 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14350 |  | 
 | 14351 |   Info = GOOD; | 
 | 14352 |   internal_command = plci->internal_command; | 
 | 14353 |   plci->internal_command = 0; | 
 | 14354 |   switch (internal_command) | 
 | 14355 |   { | 
 | 14356 |   default: | 
 | 14357 |     plci->command = 0; | 
 | 14358 |   case RTP_CONNECT_B3_REQ_COMMAND_1: | 
 | 14359 |     if (plci_nl_busy (plci)) | 
 | 14360 |     { | 
 | 14361 |       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1; | 
 | 14362 |       return; | 
 | 14363 |     } | 
 | 14364 |     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2; | 
 | 14365 |     nl_req_ncci (plci, N_CONNECT, 0); | 
 | 14366 |     send_req (plci); | 
 | 14367 |     return; | 
 | 14368 |   case RTP_CONNECT_B3_REQ_COMMAND_2: | 
 | 14369 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 14370 |     { | 
 | 14371 |       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x", | 
 | 14372 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 14373 |       Info = _WRONG_STATE; | 
 | 14374 |       break; | 
 | 14375 |     } | 
 | 14376 |     if (plci_nl_busy (plci)) | 
 | 14377 |     { | 
 | 14378 |       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2; | 
 | 14379 |       return; | 
 | 14380 |     } | 
 | 14381 |     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3; | 
 | 14382 |     plci->NData[0].PLength = plci->internal_req_buffer[0]; | 
 | 14383 |     plci->NData[0].P = plci->internal_req_buffer + 1; | 
 | 14384 |     plci->NL.X = plci->NData; | 
 | 14385 |     plci->NL.ReqCh = 0; | 
 | 14386 |     plci->NL.Req = plci->nl_req = (byte) N_UDATA; | 
 | 14387 |     plci->adapter->request (&plci->NL); | 
 | 14388 |     break; | 
 | 14389 |   case RTP_CONNECT_B3_REQ_COMMAND_3: | 
 | 14390 |     return; | 
 | 14391 |   } | 
 | 14392 |   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info); | 
 | 14393 | } | 
 | 14394 |  | 
 | 14395 |  | 
 | 14396 | static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14397 | { | 
 | 14398 |   word Info; | 
 | 14399 |   word internal_command; | 
 | 14400 |  | 
 | 14401 |   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x", | 
 | 14402 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14403 |  | 
 | 14404 |   Info = GOOD; | 
 | 14405 |   internal_command = plci->internal_command; | 
 | 14406 |   plci->internal_command = 0; | 
 | 14407 |   switch (internal_command) | 
 | 14408 |   { | 
 | 14409 |   default: | 
 | 14410 |     plci->command = 0; | 
 | 14411 |   case RTP_CONNECT_B3_RES_COMMAND_1: | 
 | 14412 |     if (plci_nl_busy (plci)) | 
 | 14413 |     { | 
 | 14414 |       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1; | 
 | 14415 |       return; | 
 | 14416 |     } | 
 | 14417 |     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2; | 
 | 14418 |     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16)); | 
 | 14419 |     send_req (plci); | 
 | 14420 |     return; | 
 | 14421 |   case RTP_CONNECT_B3_RES_COMMAND_2: | 
 | 14422 |     if ((Rc != OK) && (Rc != OK_FC)) | 
 | 14423 |     { | 
 | 14424 |       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x", | 
 | 14425 |         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc)); | 
 | 14426 |       Info = _WRONG_STATE; | 
 | 14427 |       break; | 
 | 14428 |     } | 
 | 14429 |     if (plci_nl_busy (plci)) | 
 | 14430 |     { | 
 | 14431 |       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2; | 
 | 14432 |       return; | 
 | 14433 |     } | 
 | 14434 |     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", ""); | 
 | 14435 |     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3; | 
 | 14436 |     plci->NData[0].PLength = plci->internal_req_buffer[0]; | 
 | 14437 |     plci->NData[0].P = plci->internal_req_buffer + 1; | 
 | 14438 |     plci->NL.X = plci->NData; | 
 | 14439 |     plci->NL.ReqCh = 0; | 
 | 14440 |     plci->NL.Req = plci->nl_req = (byte) N_UDATA; | 
 | 14441 |     plci->adapter->request (&plci->NL); | 
 | 14442 |     return; | 
 | 14443 |   case RTP_CONNECT_B3_RES_COMMAND_3: | 
 | 14444 |     return; | 
 | 14445 |   } | 
 | 14446 | } | 
 | 14447 |  | 
 | 14448 |  | 
 | 14449 |  | 
 | 14450 | static void hold_save_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14451 | { | 
 | 14452 |     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/ | 
 | 14453 |   word Info; | 
 | 14454 |   word internal_command; | 
 | 14455 |  | 
 | 14456 |   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x", | 
 | 14457 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14458 |  | 
 | 14459 |   Info = GOOD; | 
 | 14460 |   internal_command = plci->internal_command; | 
 | 14461 |   plci->internal_command = 0; | 
 | 14462 |   switch (internal_command) | 
 | 14463 |   { | 
 | 14464 |   default: | 
 | 14465 |     if (!plci->NL.Id) | 
 | 14466 |       break; | 
 | 14467 |     plci->command = 0; | 
 | 14468 |     plci->adjust_b_parms_msg = NULL; | 
 | 14469 |     plci->adjust_b_facilities = plci->B1_facilities; | 
 | 14470 |     plci->adjust_b_command = HOLD_SAVE_COMMAND_1; | 
 | 14471 |     plci->adjust_b_ncci = (word)(Id >> 16); | 
 | 14472 |     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23; | 
 | 14473 |     plci->adjust_b_state = ADJUST_B_START; | 
 | 14474 |     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...", | 
 | 14475 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14476 |   case HOLD_SAVE_COMMAND_1: | 
 | 14477 |     Info = adjust_b_process (Id, plci, Rc); | 
 | 14478 |     if (Info != GOOD) | 
 | 14479 |     { | 
 | 14480 |       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed", | 
 | 14481 |         UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14482 |       break; | 
 | 14483 |     } | 
 | 14484 |     if (plci->internal_command) | 
 | 14485 |       return; | 
 | 14486 |   } | 
 | 14487 |   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind); | 
 | 14488 | } | 
 | 14489 |  | 
 | 14490 |  | 
 | 14491 | static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc) | 
 | 14492 | { | 
 | 14493 |     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/ | 
 | 14494 |   word Info; | 
 | 14495 |   word internal_command; | 
 | 14496 |  | 
 | 14497 |   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x", | 
 | 14498 |     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command)); | 
 | 14499 |  | 
 | 14500 |   Info = GOOD; | 
 | 14501 |   internal_command = plci->internal_command; | 
 | 14502 |   plci->internal_command = 0; | 
 | 14503 |   switch (internal_command) | 
 | 14504 |   { | 
 | 14505 |   default: | 
 | 14506 |     plci->command = 0; | 
 | 14507 |     plci->adjust_b_parms_msg = NULL; | 
 | 14508 |     plci->adjust_b_facilities = plci->B1_facilities; | 
 | 14509 |     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1; | 
 | 14510 |     plci->adjust_b_ncci = (word)(Id >> 16); | 
 | 14511 |     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE; | 
 | 14512 |     plci->adjust_b_state = ADJUST_B_START; | 
 | 14513 |     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...", | 
 | 14514 |       UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14515 |   case RETRIEVE_RESTORE_COMMAND_1: | 
 | 14516 |     Info = adjust_b_process (Id, plci, Rc); | 
 | 14517 |     if (Info != GOOD) | 
 | 14518 |     { | 
 | 14519 |       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed", | 
 | 14520 |         UnMapId (Id), (char   *)(FILE_), __LINE__)); | 
 | 14521 |       break; | 
 | 14522 |     } | 
 | 14523 |     if (plci->internal_command) | 
 | 14524 |       return; | 
 | 14525 |   } | 
 | 14526 |   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind); | 
 | 14527 | } | 
 | 14528 |  | 
 | 14529 |  | 
 | 14530 | static void init_b1_config (PLCI   *plci) | 
 | 14531 | { | 
 | 14532 |  | 
 | 14533 |   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config", | 
 | 14534 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 14535 |     (char   *)(FILE_), __LINE__)); | 
 | 14536 |  | 
 | 14537 |   plci->B1_resource = 0; | 
 | 14538 |   plci->B1_facilities = 0; | 
 | 14539 |  | 
 | 14540 |   plci->li_bchannel_id = 0; | 
 | 14541 |   mixer_clear_config (plci); | 
 | 14542 |  | 
 | 14543 |  | 
 | 14544 |   ec_clear_config (plci); | 
 | 14545 |  | 
 | 14546 |  | 
 | 14547 |   dtmf_rec_clear_config (plci); | 
 | 14548 |   dtmf_send_clear_config (plci); | 
 | 14549 |   dtmf_parameter_clear_config (plci); | 
 | 14550 |  | 
 | 14551 |   adv_voice_clear_config (plci); | 
 | 14552 |   adjust_b_clear (plci); | 
 | 14553 | } | 
 | 14554 |  | 
 | 14555 |  | 
 | 14556 | static void clear_b1_config (PLCI   *plci) | 
 | 14557 | { | 
 | 14558 |  | 
 | 14559 |   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config", | 
 | 14560 |     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | 
 | 14561 |     (char   *)(FILE_), __LINE__)); | 
 | 14562 |  | 
 | 14563 |   adv_voice_clear_config (plci); | 
 | 14564 |   adjust_b_clear (plci); | 
 | 14565 |  | 
 | 14566 |   ec_clear_config (plci); | 
 | 14567 |  | 
 | 14568 |  | 
 | 14569 |   dtmf_rec_clear_config (plci); | 
 | 14570 |   dtmf_send_clear_config (plci); | 
 | 14571 |   dtmf_parameter_clear_config (plci); | 
 | 14572 |  | 
 | 14573 |  | 
 | 14574 |   if ((plci->li_bchannel_id != 0) | 
 | 14575 |    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | 
 | 14576 |   { | 
 | 14577 |     mixer_clear_config (plci); | 
 | 14578 |     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL; | 
 | 14579 |     plci->li_bchannel_id = 0; | 
 | 14580 |   } | 
 | 14581 |  | 
 | 14582 |   plci->B1_resource = 0; | 
 | 14583 |   plci->B1_facilities = 0; | 
 | 14584 | } | 
 | 14585 |  | 
 | 14586 |  | 
 | 14587 | /* ----------------------------------------------------------------- | 
 | 14588 |                 XON protocol local helpers | 
 | 14589 |    ----------------------------------------------------------------- */ | 
 | 14590 | static void channel_flow_control_remove (PLCI   * plci) { | 
 | 14591 |   DIVA_CAPI_ADAPTER   * a = plci->adapter; | 
 | 14592 |   word i; | 
 | 14593 |   for(i=1;i<MAX_NL_CHANNEL+1;i++) { | 
 | 14594 |     if (a->ch_flow_plci[i] == plci->Id) { | 
 | 14595 |       a->ch_flow_plci[i] = 0; | 
 | 14596 |       a->ch_flow_control[i] = 0; | 
 | 14597 |     } | 
 | 14598 |   } | 
 | 14599 | } | 
 | 14600 |  | 
 | 14601 | static void channel_x_on (PLCI   * plci, byte ch) { | 
 | 14602 |   DIVA_CAPI_ADAPTER   * a = plci->adapter; | 
 | 14603 |   if (a->ch_flow_control[ch] & N_XON_SENT) { | 
 | 14604 |     a->ch_flow_control[ch] &= ~N_XON_SENT; | 
 | 14605 |   } | 
 | 14606 | } | 
 | 14607 |  | 
 | 14608 | static void channel_x_off (PLCI   * plci, byte ch, byte flag) { | 
 | 14609 |   DIVA_CAPI_ADAPTER   * a = plci->adapter; | 
 | 14610 |   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) { | 
 | 14611 |     a->ch_flow_control[ch] |= (N_CH_XOFF | flag); | 
 | 14612 |     a->ch_flow_plci[ch] = plci->Id; | 
 | 14613 |     a->ch_flow_control_pending++; | 
 | 14614 |   } | 
 | 14615 | } | 
 | 14616 |  | 
 | 14617 | static void channel_request_xon (PLCI   * plci, byte ch) { | 
 | 14618 |   DIVA_CAPI_ADAPTER   * a = plci->adapter; | 
 | 14619 |  | 
 | 14620 |   if (a->ch_flow_control[ch] & N_CH_XOFF) { | 
 | 14621 |     a->ch_flow_control[ch] |= N_XON_REQ; | 
 | 14622 |     a->ch_flow_control[ch] &= ~N_CH_XOFF; | 
 | 14623 |     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND; | 
 | 14624 |   } | 
 | 14625 | } | 
 | 14626 |  | 
 | 14627 | static void channel_xmit_extended_xon (PLCI   * plci) { | 
 | 14628 |   DIVA_CAPI_ADAPTER   * a; | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 14629 |   int max_ch = ARRAY_SIZE(a->ch_flow_control); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14630 |   int i, one_requested = 0; | 
 | 14631 |  | 
| Harvey Harrison | dd58c0d | 2008-04-28 02:14:39 -0700 | [diff] [blame] | 14632 |   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14633 |     return; | 
 | 14634 |   } | 
 | 14635 |  | 
 | 14636 |   for (i = 0; i < max_ch; i++) { | 
 | 14637 |     if ((a->ch_flow_control[i] & N_CH_XOFF) && | 
 | 14638 |         (a->ch_flow_control[i] & N_XON_CONNECT_IND) && | 
 | 14639 |         (plci->Id == a->ch_flow_plci[i])) { | 
 | 14640 |       channel_request_xon (plci, (byte)i); | 
 | 14641 |       one_requested = 1; | 
 | 14642 |     } | 
 | 14643 |   } | 
 | 14644 |  | 
 | 14645 |   if (one_requested) { | 
 | 14646 |     channel_xmit_xon (plci); | 
 | 14647 |   } | 
 | 14648 | } | 
 | 14649 |  | 
 | 14650 | /* | 
 | 14651 |   Try to xmit next X_ON | 
 | 14652 |   */ | 
 | 14653 | static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) { | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 14654 |   int max_ch = ARRAY_SIZE(a->ch_flow_control); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14655 |   int i; | 
 | 14656 |  | 
 | 14657 |   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) { | 
 | 14658 |     return (0); | 
 | 14659 |   } | 
 | 14660 |  | 
 | 14661 |   if (a->last_flow_control_ch >= max_ch) { | 
 | 14662 |     a->last_flow_control_ch = 1; | 
 | 14663 |   } | 
 | 14664 |   for (i=a->last_flow_control_ch; i < max_ch; i++) { | 
 | 14665 |     if ((a->ch_flow_control[i] & N_XON_REQ) && | 
 | 14666 |         (plci->Id == a->ch_flow_plci[i])) { | 
 | 14667 |       a->last_flow_control_ch = i+1; | 
 | 14668 |       return (i); | 
 | 14669 |     } | 
 | 14670 |   } | 
 | 14671 |  | 
 | 14672 |   for (i = 1; i < a->last_flow_control_ch; i++) { | 
 | 14673 |     if ((a->ch_flow_control[i] & N_XON_REQ) && | 
 | 14674 |         (plci->Id == a->ch_flow_plci[i])) { | 
 | 14675 |       a->last_flow_control_ch = i+1; | 
 | 14676 |       return (i); | 
 | 14677 |     } | 
 | 14678 |   } | 
 | 14679 |  | 
 | 14680 |   return (0); | 
 | 14681 | } | 
 | 14682 |  | 
 | 14683 | static void channel_xmit_xon (PLCI   * plci) { | 
 | 14684 |   DIVA_CAPI_ADAPTER   * a = plci->adapter; | 
 | 14685 |   byte ch; | 
 | 14686 |  | 
 | 14687 |   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) { | 
 | 14688 |     return; | 
 | 14689 |   } | 
 | 14690 |   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) { | 
 | 14691 |     return; | 
 | 14692 |   } | 
 | 14693 |   a->ch_flow_control[ch] &= ~N_XON_REQ; | 
 | 14694 |   a->ch_flow_control[ch] |= N_XON_SENT; | 
 | 14695 |  | 
 | 14696 |   plci->NL.Req = plci->nl_req = (byte)N_XON; | 
 | 14697 |   plci->NL.ReqCh         = ch; | 
 | 14698 |   plci->NL.X             = plci->NData; | 
 | 14699 |   plci->NL.XNum          = 1; | 
 | 14700 |   plci->NData[0].P       = &plci->RBuffer[0]; | 
 | 14701 |   plci->NData[0].PLength = 0; | 
 | 14702 |  | 
 | 14703 |   plci->adapter->request(&plci->NL); | 
 | 14704 | } | 
 | 14705 |  | 
 | 14706 | static int channel_can_xon (PLCI   * plci, byte ch) { | 
 | 14707 |   APPL   * APPLptr; | 
 | 14708 |   DIVA_CAPI_ADAPTER   * a; | 
 | 14709 |   word NCCIcode; | 
 | 14710 |   dword count; | 
 | 14711 |   word Num; | 
 | 14712 |   word i; | 
 | 14713 |  | 
 | 14714 |   APPLptr = plci->appl; | 
 | 14715 |   a = plci->adapter; | 
 | 14716 |  | 
 | 14717 |   if (!APPLptr) | 
 | 14718 |     return (0); | 
 | 14719 |  | 
 | 14720 |   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8); | 
 | 14721 |  | 
 | 14722 |                 /* count all buffers within the Application pool    */ | 
 | 14723 |                 /* belonging to the same NCCI. XON if a first is    */ | 
 | 14724 |                 /* used.                                            */ | 
 | 14725 |   count = 0; | 
 | 14726 |   Num = 0xffff; | 
 | 14727 |   for(i=0; i<APPLptr->MaxBuffer; i++) { | 
 | 14728 |     if(NCCIcode==APPLptr->DataNCCI[i]) count++; | 
 | 14729 |     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i; | 
 | 14730 |   } | 
 | 14731 |   if ((count > 2) || (Num == 0xffff)) { | 
 | 14732 |     return (0); | 
 | 14733 |   } | 
 | 14734 |   return (1); | 
 | 14735 | } | 
 | 14736 |  | 
 | 14737 |  | 
 | 14738 | /*------------------------------------------------------------------*/ | 
 | 14739 |  | 
 | 14740 | static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset) | 
 | 14741 | { | 
 | 14742 |   return 1; | 
 | 14743 | } | 
 | 14744 |  | 
 | 14745 |  | 
 | 14746 |  | 
 | 14747 | /**********************************************************************************/ | 
 | 14748 | /* function groups the listening applications according to the CIP mask and the   */ | 
 | 14749 | /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */ | 
 | 14750 | /* are not multi-instance capable, so they start e.g. 30 applications what causes */ | 
 | 14751 | /* big problems on application level (one call, 30 Connect_Ind, ect). The         */ | 
 | 14752 | /* function must be enabled by setting "a->group_optimization_enabled" from the   */ | 
 | 14753 | /* OS specific part (per adapter).                                                */ | 
 | 14754 | /**********************************************************************************/ | 
 | 14755 | static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci) | 
 | 14756 | { | 
 | 14757 |   word i,j,k,busy,group_found; | 
 | 14758 |   dword info_mask_group[MAX_CIP_TYPES]; | 
 | 14759 |   dword cip_mask_group[MAX_CIP_TYPES]; | 
 | 14760 |   word appl_number_group_type[MAX_APPL]; | 
 | 14761 |   PLCI   *auxplci; | 
 | 14762 |  | 
 | 14763 |   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */ | 
 | 14764 |  | 
 | 14765 |   if(!a->group_optimization_enabled) | 
 | 14766 |   { | 
 | 14767 |     dbug(1,dprintf("No group optimization")); | 
 | 14768 |     return; | 
 | 14769 |   } | 
 | 14770 |  | 
 | 14771 |   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled)); | 
 | 14772 |  | 
 | 14773 |   for(i=0;i<MAX_CIP_TYPES;i++) | 
 | 14774 |   { | 
 | 14775 |     info_mask_group[i] = 0; | 
 | 14776 |     cip_mask_group [i] = 0; | 
 | 14777 |   } | 
 | 14778 |   for(i=0;i<MAX_APPL;i++) | 
 | 14779 |   { | 
 | 14780 |     appl_number_group_type[i] = 0; | 
 | 14781 |   } | 
 | 14782 |   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */ | 
 | 14783 |   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */ | 
 | 14784 |     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) ) | 
 | 14785 |     { | 
 | 14786 |       dbug(1,dprintf("Multi-Instance capable, no optimization required")); | 
 | 14787 |       return; /* allow good application unfiltered access */ | 
 | 14788 |     } | 
 | 14789 |   } | 
 | 14790 |   for(i=0; i<max_appl; i++) /* Build CIP Groups */ | 
 | 14791 |   { | 
 | 14792 |     if(application[i].Id && a->CIP_Mask[i] ) | 
 | 14793 |     { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14794 |       for(k=0,busy=false; k<a->max_plci; k++) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14795 |       { | 
 | 14796 |         if(a->plci[k].Id)  | 
 | 14797 |         { | 
 | 14798 |           auxplci = &a->plci[k]; | 
 | 14799 |           if(auxplci->appl == &application[i]) /* application has a busy PLCI */ | 
 | 14800 |           { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14801 |             busy = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14802 |             dbug(1,dprintf("Appl 0x%x is busy",i+1)); | 
 | 14803 |           } | 
 | 14804 |           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */ | 
 | 14805 |           { | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14806 |             busy = true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14807 |             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1)); | 
 | 14808 |           } | 
 | 14809 |         } | 
 | 14810 |       } | 
 | 14811 |  | 
 | 14812 |       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */ | 
 | 14813 |       { | 
 | 14814 |         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */ | 
 | 14815 |         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */ | 
 | 14816 |           appl_number_group_type[i] = MAX_CIP_TYPES; | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14817 |           group_found=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14818 |           dbug(1,dprintf("Field overflow appl 0x%x",i+1)); | 
 | 14819 |         } | 
 | 14820 |         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )   | 
 | 14821 |         {                                      /* is group already present ?                  */ | 
 | 14822 |           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */ | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14823 |           group_found=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14824 |           dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j])); | 
 | 14825 |         } | 
 | 14826 |         else if(!info_mask_group[j]) | 
 | 14827 |         {                                      /* establish a new group                       */ | 
 | 14828 |           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */ | 
 | 14829 |           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */ | 
 | 14830 |           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */ | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14831 |           group_found=true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14832 |           dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j])); | 
 | 14833 |         } | 
 | 14834 |       } | 
 | 14835 |     } | 
 | 14836 |   } | 
 | 14837 |          | 
 | 14838 |   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */ | 
 | 14839 |   { | 
 | 14840 |     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */ | 
 | 14841 |     { | 
 | 14842 |       if(appl_number_group_type[i] == MAX_CIP_TYPES) | 
 | 14843 |       { | 
 | 14844 |         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1)); | 
 | 14845 |       } | 
 | 14846 |       else | 
 | 14847 |       { | 
 | 14848 |         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1)); | 
 | 14849 |         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */ | 
 | 14850 |         { | 
 | 14851 |           if(appl_number_group_type[i] == appl_number_group_type[j])  | 
 | 14852 |           { | 
 | 14853 |             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j])); | 
 | 14854 |             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */ | 
 | 14855 |             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */ | 
 | 14856 |           } | 
 | 14857 |         } | 
 | 14858 |       } | 
 | 14859 |     } | 
 | 14860 |     else                                                 /* application should not get a call */ | 
 | 14861 |     { | 
 | 14862 |       clear_group_ind_mask_bit (plci, i); | 
 | 14863 |     } | 
 | 14864 |   } | 
 | 14865 |  | 
 | 14866 | } | 
 | 14867 |  | 
 | 14868 |  | 
 | 14869 |  | 
 | 14870 | /* OS notifies the driver about a application Capi_Register */ | 
 | 14871 | word CapiRegister(word id) | 
 | 14872 | { | 
 | 14873 |   word i,j,appls_found; | 
 | 14874 |  | 
 | 14875 |   PLCI   *plci; | 
 | 14876 |   DIVA_CAPI_ADAPTER   *a; | 
 | 14877 |  | 
 | 14878 |   for(i=0,appls_found=0; i<max_appl; i++) | 
 | 14879 |   { | 
 | 14880 |     if( application[i].Id && (application[i].Id!=id) ) | 
 | 14881 |     { | 
 | 14882 |       appls_found++;                       /* an application has been found */ | 
 | 14883 |     } | 
 | 14884 |   } | 
 | 14885 |  | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14886 |   if(appls_found) return true; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14887 |   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */ | 
 | 14888 |   { | 
 | 14889 |     a = &adapter[i]; | 
 | 14890 |     if(a->request) | 
 | 14891 |     { | 
 | 14892 |       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */ | 
 | 14893 |       { | 
 | 14894 |         if(!appls_found)           /* first application does a capi register   */ | 
 | 14895 |         { | 
 | 14896 |           if((j=get_plci(a)))                    /* activate L1 of all adapters */ | 
 | 14897 |           { | 
 | 14898 |             plci = &a->plci[j-1]; | 
 | 14899 |             plci->command = 0; | 
 | 14900 |             add_p(plci,OAD,"\x01\xfd"); | 
 | 14901 |             add_p(plci,CAI,"\x01\x80"); | 
 | 14902 |             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | 
 | 14903 |             add_p(plci,SHIFT|6,NULL); | 
 | 14904 |             add_p(plci,SIN,"\x02\x00\x00"); | 
 | 14905 |             plci->internal_command = START_L1_SIG_ASSIGN_PEND; | 
 | 14906 |             sig_req(plci,ASSIGN,DSIG_ID); | 
 | 14907 |             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */ | 
 | 14908 |             sig_req(plci,SIG_CTRL,0); | 
 | 14909 |             send_req(plci); | 
 | 14910 |           } | 
 | 14911 |         } | 
 | 14912 |       } | 
 | 14913 |     } | 
 | 14914 |   } | 
| Richard Knutsson | 986c4bb | 2007-02-12 00:53:24 -0800 | [diff] [blame] | 14915 |   return false; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14916 | } | 
 | 14917 |  | 
 | 14918 | /*------------------------------------------------------------------*/ | 
 | 14919 |  | 
 | 14920 | /* Functions for virtual Switching e.g. Transfer by join, Conference */ | 
 | 14921 |  | 
 | 14922 | static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms) | 
 | 14923 | { | 
 | 14924 |  word i; | 
 | 14925 |  /* Format of vswitch_t: | 
 | 14926 |  0 byte length | 
 | 14927 |  1 byte VSWITCHIE | 
 | 14928 |  2 byte VSWITCH_REQ/VSWITCH_IND | 
 | 14929 |  3 byte reserved | 
 | 14930 |  4 word VSwitchcommand | 
 | 14931 |  6 word returnerror | 
 | 14932 |  8... Params | 
 | 14933 |  */ | 
 | 14934 |  if(!plci || | 
 | 14935 |   !plci->appl || | 
 | 14936 |   !plci->State || | 
 | 14937 |   plci->Sig.Ind==NCR_FACILITY | 
 | 14938 |   ) | 
 | 14939 |   return; | 
 | 14940 |   | 
 | 14941 |  for(i=0;i<MAX_MULTI_IE;i++) | 
 | 14942 |  { | 
 | 14943 |         if(!parms[i][0]) continue; | 
 | 14944 |   if(parms[i][0]<7) | 
 | 14945 |   { | 
 | 14946 |    parms[i][0]=0; /* kill it */ | 
 | 14947 |    continue; | 
 | 14948 |   } | 
 | 14949 |   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4])); | 
 | 14950 |   switch(parms[i][4]) | 
 | 14951 |   { | 
 | 14952 |   case VSJOIN: | 
 | 14953 |    if(!plci->relatedPTYPLCI || | 
 | 14954 |     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT)) | 
 | 14955 |    { /* Error */ | 
 | 14956 |     break; | 
 | 14957 |    } | 
 | 14958 |    /* remember all necessary informations */ | 
 | 14959 |    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */ | 
 | 14960 |    { | 
 | 14961 |     break; | 
 | 14962 |    } | 
 | 14963 |    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1) | 
 | 14964 |    {   /* first indication after ECT-Request on Consultation Call */ | 
 | 14965 |     plci->vswitchstate=parms[i][9]; | 
 | 14966 |     parms[i][9]=2; /* State */ | 
 | 14967 |     /* now ask first Call to join */ | 
 | 14968 |    } | 
 | 14969 |    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3) | 
 | 14970 |    { /* Answer of VSWITCH_REQ from first Call */ | 
 | 14971 |     plci->vswitchstate=parms[i][9]; | 
 | 14972 |     /* tell consultation call to join | 
 | 14973 |     and the protocol capabilities of the first call */ | 
 | 14974 |    } | 
 | 14975 |    else | 
 | 14976 |    { /* Error */ | 
 | 14977 |     break; | 
 | 14978 |    }     | 
 | 14979 |    plci->vsprot=parms[i][10]; /* protocol */ | 
 | 14980 |    plci->vsprotdialect=parms[i][11]; /* protocoldialect */ | 
 | 14981 |    /* send join request to related PLCI */ | 
 | 14982 |    parms[i][1]=VSWITCHIE; | 
 | 14983 |    parms[i][2]=VSWITCH_REQ; | 
 | 14984 |     | 
 | 14985 |    plci->relatedPTYPLCI->command = 0; | 
 | 14986 |    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND; | 
 | 14987 |    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]); | 
 | 14988 |    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0); | 
 | 14989 |    send_req(plci->relatedPTYPLCI); | 
 | 14990 |    break; | 
 | 14991 |   case VSTRANSPORT: | 
 | 14992 |   default: | 
 | 14993 |    if(plci->relatedPTYPLCI && | 
 | 14994 |     plci->vswitchstate==3 && | 
 | 14995 |     plci->relatedPTYPLCI->vswitchstate==3) | 
 | 14996 |    { | 
 | 14997 |     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]); | 
 | 14998 |     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0); | 
 | 14999 |     send_req(plci->relatedPTYPLCI); | 
 | 15000 |    } | 
 | 15001 |    break; | 
 | 15002 |   }   | 
 | 15003 |   parms[i][0]=0; /* kill it */ | 
 | 15004 |  } | 
 | 15005 | } | 
 | 15006 |  | 
 | 15007 |  | 
 | 15008 | /*------------------------------------------------------------------*/ | 
 | 15009 |  | 
 | 15010 | static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) { | 
 | 15011 |   ENTITY e; | 
 | 15012 |   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; | 
 | 15013 |  | 
 | 15014 |   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) { | 
 | 15015 |     return (-1); | 
 | 15016 |   } | 
 | 15017 |  | 
 | 15018 |   pReq->xdi_dma_descriptor_operation.Req = 0; | 
 | 15019 |   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; | 
 | 15020 |  | 
 | 15021 |   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC; | 
 | 15022 |   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1; | 
 | 15023 |   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; | 
 | 15024 |   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0; | 
 | 15025 |  | 
 | 15026 |   e.user[0] = plci->adapter->Id - 1; | 
 | 15027 |   plci->adapter->request((ENTITY*)pReq); | 
 | 15028 |  | 
 | 15029 |   if (!pReq->xdi_dma_descriptor_operation.info.operation && | 
 | 15030 |       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) && | 
 | 15031 |       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) { | 
 | 15032 |     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic; | 
 | 15033 |     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)", | 
 | 15034 |          plci->adapter->Id, | 
 | 15035 |          pReq->xdi_dma_descriptor_operation.info.descriptor_number, | 
 | 15036 |          *dma_magic)); | 
 | 15037 |     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number); | 
 | 15038 |   } else { | 
 | 15039 |     dbug(1,dprintf("dma_alloc failed")); | 
 | 15040 |     return (-1); | 
 | 15041 |   } | 
 | 15042 | } | 
 | 15043 |  | 
 | 15044 | static void diva_free_dma_descriptor (PLCI   *plci, int nr) { | 
 | 15045 |   ENTITY e; | 
 | 15046 |   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; | 
 | 15047 |  | 
 | 15048 |   if (nr < 0) { | 
 | 15049 |     return; | 
 | 15050 |   } | 
 | 15051 |  | 
 | 15052 |   pReq->xdi_dma_descriptor_operation.Req = 0; | 
 | 15053 |   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; | 
 | 15054 |  | 
 | 15055 |   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE; | 
 | 15056 |   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr; | 
 | 15057 |   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; | 
 | 15058 |   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0; | 
 | 15059 |  | 
 | 15060 |   e.user[0] = plci->adapter->Id - 1; | 
 | 15061 |   plci->adapter->request((ENTITY*)pReq); | 
 | 15062 |  | 
 | 15063 |   if (!pReq->xdi_dma_descriptor_operation.info.operation) { | 
 | 15064 |     dbug(1,dprintf("dma_free(%d)", nr)); | 
 | 15065 |   } else { | 
 | 15066 |     dbug(1,dprintf("dma_free failed (%d)", nr)); | 
 | 15067 |   } | 
 | 15068 | } | 
 | 15069 |  | 
 | 15070 | /*------------------------------------------------------------------*/ |