Deleted Added
full compact
uipaq.c (187970) uipaq.c (188413)
1/* $NetBSD: uipaq.c,v 1.4 2006/11/16 01:33:27 christos Exp $ */
2/* $OpenBSD: uipaq.c,v 1.1 2005/06/17 23:50:33 deraadt Exp $ */
3
4/*
5 * Copyright (c) 2000-2005 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation

--- 35 unchanged lines hidden (view full) ---

44 * 19 July 2003: Incorporated changes suggested by Sam Lawrance from
45 * the uppc module
46 *
47 *
48 * Contact isis@cs.umd.edu if you have any questions/comments about this driver
49 */
50
51#include <sys/cdefs.h>
1/* $NetBSD: uipaq.c,v 1.4 2006/11/16 01:33:27 christos Exp $ */
2/* $OpenBSD: uipaq.c,v 1.1 2005/06/17 23:50:33 deraadt Exp $ */
3
4/*
5 * Copyright (c) 2000-2005 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation

--- 35 unchanged lines hidden (view full) ---

44 * 19 July 2003: Incorporated changes suggested by Sam Lawrance from
45 * the uppc module
46 *
47 *
48 * Contact isis@cs.umd.edu if you have any questions/comments about this driver
49 */
50
51#include <sys/cdefs.h>
52__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/uipaq2.c 187970 2009-02-01 00:51:25Z thompsa $");
52__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/uipaq2.c 188413 2009-02-09 22:05:25Z thompsa $");
53
54#include <dev/usb2/include/usb2_devid.h>
55#include <dev/usb2/include/usb2_standard.h>
56#include <dev/usb2/include/usb2_mfunc.h>
57#include <dev/usb2/include/usb2_error.h>
58#include <dev/usb2/include/usb2_cdc.h>
59
60#define USB_DEBUG_VAR usb2_debug

--- 11 unchanged lines hidden (view full) ---

72#define UIPAQ_CONFIG_INDEX 0 /* config number 1 */
73#define UIPAQ_IFACE_INDEX 0
74
75#define UIPAQ_BUF_SIZE 1024
76
77enum {
78 UIPAQ_BULK_DT_WR,
79 UIPAQ_BULK_DT_RD,
53
54#include <dev/usb2/include/usb2_devid.h>
55#include <dev/usb2/include/usb2_standard.h>
56#include <dev/usb2/include/usb2_mfunc.h>
57#include <dev/usb2/include/usb2_error.h>
58#include <dev/usb2/include/usb2_cdc.h>
59
60#define USB_DEBUG_VAR usb2_debug

--- 11 unchanged lines hidden (view full) ---

72#define UIPAQ_CONFIG_INDEX 0 /* config number 1 */
73#define UIPAQ_IFACE_INDEX 0
74
75#define UIPAQ_BUF_SIZE 1024
76
77enum {
78 UIPAQ_BULK_DT_WR,
79 UIPAQ_BULK_DT_RD,
80 UIPAQ_BULK_CS_WR,
81 UIPAQ_BULK_CS_RD,
82 UIPAQ_N_TRANSFER = 4,
80 UIPAQ_N_TRANSFER,
83};
84
85struct uipaq_softc {
86 struct usb2_com_super_softc sc_super_ucom;
87 struct usb2_com_softc sc_ucom;
88
89 struct usb2_xfer *sc_xfer[UIPAQ_N_TRANSFER];
90 struct usb2_device *sc_udev;
91
92 uint16_t sc_line;
93
94 uint8_t sc_lsr; /* local status register */
95 uint8_t sc_msr; /* modem status register */
81};
82
83struct uipaq_softc {
84 struct usb2_com_super_softc sc_super_ucom;
85 struct usb2_com_softc sc_ucom;
86
87 struct usb2_xfer *sc_xfer[UIPAQ_N_TRANSFER];
88 struct usb2_device *sc_udev;
89
90 uint16_t sc_line;
91
92 uint8_t sc_lsr; /* local status register */
93 uint8_t sc_msr; /* modem status register */
96 uint8_t sc_flag;
97#define UIPAQ_FLAG_READ_STALL 0x01
98#define UIPAQ_FLAG_WRITE_STALL 0x02
99#define UIPAQ_FLAG_INTR_STALL 0x04
100};
101
102static device_probe_t uipaq_probe;
103static device_attach_t uipaq_attach;
104static device_detach_t uipaq_detach;
105
106static usb2_callback_t uipaq_write_callback;
107static usb2_callback_t uipaq_read_callback;
94};
95
96static device_probe_t uipaq_probe;
97static device_attach_t uipaq_attach;
98static device_detach_t uipaq_detach;
99
100static usb2_callback_t uipaq_write_callback;
101static usb2_callback_t uipaq_read_callback;
108static usb2_callback_t uipaq_write_clear_stall_callback;
109static usb2_callback_t uipaq_read_clear_stall_callback;
110
111static void uipaq_start_read(struct usb2_com_softc *);
112static void uipaq_stop_read(struct usb2_com_softc *);
113static void uipaq_start_write(struct usb2_com_softc *);
114static void uipaq_stop_write(struct usb2_com_softc *);
102
103static void uipaq_start_read(struct usb2_com_softc *);
104static void uipaq_stop_read(struct usb2_com_softc *);
105static void uipaq_start_write(struct usb2_com_softc *);
106static void uipaq_stop_write(struct usb2_com_softc *);
115static void uipaq_cfg_do_request(struct uipaq_softc *,
116 struct usb2_device_request *, void *);
117static void uipaq_cfg_set_dtr(struct usb2_com_softc *, uint8_t);
118static void uipaq_cfg_set_rts(struct usb2_com_softc *, uint8_t);
119static void uipaq_cfg_set_break(struct usb2_com_softc *, uint8_t);
120
121static const struct usb2_config uipaq_config_data[UIPAQ_N_TRANSFER] = {
122
123 [UIPAQ_BULK_DT_WR] = {
124 .type = UE_BULK,

--- 7 unchanged lines hidden (view full) ---

132 [UIPAQ_BULK_DT_RD] = {
133 .type = UE_BULK,
134 .endpoint = UE_ADDR_ANY,
135 .direction = UE_DIR_IN,
136 .mh.bufsize = UIPAQ_BUF_SIZE,
137 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
138 .mh.callback = &uipaq_read_callback,
139 },
107static void uipaq_cfg_set_dtr(struct usb2_com_softc *, uint8_t);
108static void uipaq_cfg_set_rts(struct usb2_com_softc *, uint8_t);
109static void uipaq_cfg_set_break(struct usb2_com_softc *, uint8_t);
110
111static const struct usb2_config uipaq_config_data[UIPAQ_N_TRANSFER] = {
112
113 [UIPAQ_BULK_DT_WR] = {
114 .type = UE_BULK,

--- 7 unchanged lines hidden (view full) ---

122 [UIPAQ_BULK_DT_RD] = {
123 .type = UE_BULK,
124 .endpoint = UE_ADDR_ANY,
125 .direction = UE_DIR_IN,
126 .mh.bufsize = UIPAQ_BUF_SIZE,
127 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
128 .mh.callback = &uipaq_read_callback,
129 },
140
141 [UIPAQ_BULK_CS_WR] = {
142 .type = UE_CONTROL,
143 .endpoint = 0x00, /* Control pipe */
144 .direction = UE_DIR_ANY,
145 .mh.bufsize = sizeof(struct usb2_device_request),
146 .mh.callback = &uipaq_write_clear_stall_callback,
147 .mh.timeout = 1000, /* 1 second */
148 .mh.interval = 50, /* 50ms */
149 },
150
151 [UIPAQ_BULK_CS_RD] = {
152 .type = UE_CONTROL,
153 .endpoint = 0x00, /* Control pipe */
154 .direction = UE_DIR_ANY,
155 .mh.bufsize = sizeof(struct usb2_device_request),
156 .mh.callback = &uipaq_read_clear_stall_callback,
157 .mh.timeout = 1000, /* 1 second */
158 .mh.interval = 50, /* 50ms */
159 },
160};
161
162static const struct usb2_com_callback uipaq_callback = {
163 .usb2_com_cfg_set_dtr = &uipaq_cfg_set_dtr,
164 .usb2_com_cfg_set_rts = &uipaq_cfg_set_rts,
165 .usb2_com_cfg_set_break = &uipaq_cfg_set_break,
166 .usb2_com_start_read = &uipaq_start_read,
167 .usb2_com_stop_read = &uipaq_stop_read,

--- 976 unchanged lines hidden (view full) ---

1144 USETW(req.wIndex, 0x0);
1145 USETW(req.wLength, 0);
1146 for (i = 0; i != 64; i++) {
1147 error =
1148 usb2_do_request_flags(uaa->device, NULL, &req,
1149 NULL, 0, NULL, 100);
1150 if (error == 0)
1151 break;
130};
131
132static const struct usb2_com_callback uipaq_callback = {
133 .usb2_com_cfg_set_dtr = &uipaq_cfg_set_dtr,
134 .usb2_com_cfg_set_rts = &uipaq_cfg_set_rts,
135 .usb2_com_cfg_set_break = &uipaq_cfg_set_break,
136 .usb2_com_start_read = &uipaq_start_read,
137 .usb2_com_stop_read = &uipaq_stop_read,

--- 976 unchanged lines hidden (view full) ---

1114 USETW(req.wIndex, 0x0);
1115 USETW(req.wLength, 0);
1116 for (i = 0; i != 64; i++) {
1117 error =
1118 usb2_do_request_flags(uaa->device, NULL, &req,
1119 NULL, 0, NULL, 100);
1120 if (error == 0)
1121 break;
1152 usb2_pause_mtx(NULL, 100);
1122 usb2_pause_mtx(NULL, hz / 10);
1153 }
1154
1155 iface_index = UIPAQ_IFACE_INDEX;
1156 error = usb2_transfer_setup(uaa->device, &iface_index,
1157 sc->sc_xfer, uipaq_config_data,
1158 UIPAQ_N_TRANSFER, sc, &Giant);
1159
1160 if (error) {
1161 goto detach;
1162 }
1163 /* clear stall at first run */
1123 }
1124
1125 iface_index = UIPAQ_IFACE_INDEX;
1126 error = usb2_transfer_setup(uaa->device, &iface_index,
1127 sc->sc_xfer, uipaq_config_data,
1128 UIPAQ_N_TRANSFER, sc, &Giant);
1129
1130 if (error) {
1131 goto detach;
1132 }
1133 /* clear stall at first run */
1164 sc->sc_flag |= (UIPAQ_FLAG_READ_STALL |
1165 UIPAQ_FLAG_WRITE_STALL);
1134 usb2_transfer_set_stall(sc->sc_xfer[UIPAQ_BULK_DT_WR]);
1135 usb2_transfer_set_stall(sc->sc_xfer[UIPAQ_BULK_DT_RD]);
1166
1167 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
1168 &uipaq_callback, &Giant);
1169 if (error) {
1170 goto detach;
1171 }
1172 return (0);
1173

--- 24 unchanged lines hidden (view full) ---

1198}
1199
1200static void
1201uipaq_stop_read(struct usb2_com_softc *ucom)
1202{
1203 struct uipaq_softc *sc = ucom->sc_parent;
1204
1205 /* stop read endpoint */
1136
1137 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
1138 &uipaq_callback, &Giant);
1139 if (error) {
1140 goto detach;
1141 }
1142 return (0);
1143

--- 24 unchanged lines hidden (view full) ---

1168}
1169
1170static void
1171uipaq_stop_read(struct usb2_com_softc *ucom)
1172{
1173 struct uipaq_softc *sc = ucom->sc_parent;
1174
1175 /* stop read endpoint */
1206 usb2_transfer_stop(sc->sc_xfer[UIPAQ_BULK_CS_RD]);
1207 usb2_transfer_stop(sc->sc_xfer[UIPAQ_BULK_DT_RD]);
1208}
1209
1210static void
1211uipaq_start_write(struct usb2_com_softc *ucom)
1212{
1213 struct uipaq_softc *sc = ucom->sc_parent;
1214
1215 usb2_transfer_start(sc->sc_xfer[UIPAQ_BULK_DT_WR]);
1216}
1217
1218static void
1219uipaq_stop_write(struct usb2_com_softc *ucom)
1220{
1221 struct uipaq_softc *sc = ucom->sc_parent;
1222
1176 usb2_transfer_stop(sc->sc_xfer[UIPAQ_BULK_DT_RD]);
1177}
1178
1179static void
1180uipaq_start_write(struct usb2_com_softc *ucom)
1181{
1182 struct uipaq_softc *sc = ucom->sc_parent;
1183
1184 usb2_transfer_start(sc->sc_xfer[UIPAQ_BULK_DT_WR]);
1185}
1186
1187static void
1188uipaq_stop_write(struct usb2_com_softc *ucom)
1189{
1190 struct uipaq_softc *sc = ucom->sc_parent;
1191
1223 usb2_transfer_stop(sc->sc_xfer[UIPAQ_BULK_CS_WR]);
1224 usb2_transfer_stop(sc->sc_xfer[UIPAQ_BULK_DT_WR]);
1225}
1226
1227static void
1192 usb2_transfer_stop(sc->sc_xfer[UIPAQ_BULK_DT_WR]);
1193}
1194
1195static void
1228uipaq_cfg_do_request(struct uipaq_softc *sc, struct usb2_device_request *req,
1229 void *data)
1230{
1231 uint16_t length;
1232 usb2_error_t err;
1233
1234 if (usb2_com_cfg_is_gone(&sc->sc_ucom)) {
1235 goto error;
1236 }
1237 err = usb2_do_request(sc->sc_udev, &Giant, req, data);
1238
1239 if (err) {
1240
1241 DPRINTFN(0, "device request failed, err=%s "
1242 "(ignored)\n", usb2_errstr(err));
1243
1244error:
1245 length = UGETW(req->wLength);
1246
1247 if ((req->bmRequestType & UT_READ) && length) {
1248 bzero(data, length);
1249 }
1250 }
1251}
1252
1253static void
1254uipaq_cfg_set_dtr(struct usb2_com_softc *ucom, uint8_t onoff)
1255{
1256 struct uipaq_softc *sc = ucom->sc_parent;
1257 struct usb2_device_request req;
1258
1259 DPRINTF("onoff=%d\n", onoff);
1260
1261 if (onoff)
1262 sc->sc_line |= UCDC_LINE_DTR;
1263 else
1264 sc->sc_line &= ~UCDC_LINE_DTR;
1265
1266 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1267 req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
1268 USETW(req.wValue, sc->sc_line);
1269 req.wIndex[0] = UIPAQ_IFACE_INDEX;
1270 req.wIndex[1] = 0;
1271 USETW(req.wLength, 0);
1272
1196uipaq_cfg_set_dtr(struct usb2_com_softc *ucom, uint8_t onoff)
1197{
1198 struct uipaq_softc *sc = ucom->sc_parent;
1199 struct usb2_device_request req;
1200
1201 DPRINTF("onoff=%d\n", onoff);
1202
1203 if (onoff)
1204 sc->sc_line |= UCDC_LINE_DTR;
1205 else
1206 sc->sc_line &= ~UCDC_LINE_DTR;
1207
1208 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1209 req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
1210 USETW(req.wValue, sc->sc_line);
1211 req.wIndex[0] = UIPAQ_IFACE_INDEX;
1212 req.wIndex[1] = 0;
1213 USETW(req.wLength, 0);
1214
1273 uipaq_cfg_do_request(sc, &req, NULL);
1215 usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
1216 &req, NULL, 0, 1000);
1274}
1275
1276static void
1277uipaq_cfg_set_rts(struct usb2_com_softc *ucom, uint8_t onoff)
1278{
1279 struct uipaq_softc *sc = ucom->sc_parent;
1280 struct usb2_device_request req;
1281

--- 6 unchanged lines hidden (view full) ---

1288
1289 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1290 req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
1291 USETW(req.wValue, sc->sc_line);
1292 req.wIndex[0] = UIPAQ_IFACE_INDEX;
1293 req.wIndex[1] = 0;
1294 USETW(req.wLength, 0);
1295
1217}
1218
1219static void
1220uipaq_cfg_set_rts(struct usb2_com_softc *ucom, uint8_t onoff)
1221{
1222 struct uipaq_softc *sc = ucom->sc_parent;
1223 struct usb2_device_request req;
1224

--- 6 unchanged lines hidden (view full) ---

1231
1232 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1233 req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
1234 USETW(req.wValue, sc->sc_line);
1235 req.wIndex[0] = UIPAQ_IFACE_INDEX;
1236 req.wIndex[1] = 0;
1237 USETW(req.wLength, 0);
1238
1296 uipaq_cfg_do_request(sc, &req, NULL);
1239 usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
1240 &req, NULL, 0, 1000);
1297}
1298
1299static void
1300uipaq_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
1301{
1302 struct uipaq_softc *sc = ucom->sc_parent;
1303 struct usb2_device_request req;
1304 uint16_t temp;
1305
1306 temp = onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF;
1307
1308 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1309 req.bRequest = UCDC_SEND_BREAK;
1310 USETW(req.wValue, temp);
1311 req.wIndex[0] = UIPAQ_IFACE_INDEX;
1312 req.wIndex[1] = 0;
1313 USETW(req.wLength, 0);
1314
1241}
1242
1243static void
1244uipaq_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
1245{
1246 struct uipaq_softc *sc = ucom->sc_parent;
1247 struct usb2_device_request req;
1248 uint16_t temp;
1249
1250 temp = onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF;
1251
1252 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1253 req.bRequest = UCDC_SEND_BREAK;
1254 USETW(req.wValue, temp);
1255 req.wIndex[0] = UIPAQ_IFACE_INDEX;
1256 req.wIndex[1] = 0;
1257 USETW(req.wLength, 0);
1258
1315 uipaq_cfg_do_request(sc, &req, NULL);
1259 usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
1260 &req, NULL, 0, 1000);
1316}
1317
1318static void
1319uipaq_write_callback(struct usb2_xfer *xfer)
1320{
1321 struct uipaq_softc *sc = xfer->priv_sc;
1322 uint32_t actlen;
1323
1324 switch (USB_GET_STATE(xfer)) {
1325 case USB_ST_SETUP:
1326 case USB_ST_TRANSFERRED:
1261}
1262
1263static void
1264uipaq_write_callback(struct usb2_xfer *xfer)
1265{
1266 struct uipaq_softc *sc = xfer->priv_sc;
1267 uint32_t actlen;
1268
1269 switch (USB_GET_STATE(xfer)) {
1270 case USB_ST_SETUP:
1271 case USB_ST_TRANSFERRED:
1327 if (sc->sc_flag & UIPAQ_FLAG_WRITE_STALL) {
1328 usb2_transfer_start(sc->sc_xfer[UIPAQ_BULK_CS_WR]);
1329 return;
1330 }
1272tr_setup:
1331 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
1332 UIPAQ_BUF_SIZE, &actlen)) {
1273 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
1274 UIPAQ_BUF_SIZE, &actlen)) {
1333
1334 xfer->frlengths[0] = actlen;
1335 usb2_start_hardware(xfer);
1336 }
1337 return;
1338
1339 default: /* Error */
1340 if (xfer->error != USB_ERR_CANCELLED) {
1275 xfer->frlengths[0] = actlen;
1276 usb2_start_hardware(xfer);
1277 }
1278 return;
1279
1280 default: /* Error */
1281 if (xfer->error != USB_ERR_CANCELLED) {
1341 sc->sc_flag |= UIPAQ_FLAG_WRITE_STALL;
1342 usb2_transfer_start(sc->sc_xfer[UIPAQ_BULK_CS_WR]);
1282 /* try to clear stall first */
1283 xfer->flags.stall_pipe = 1;
1284 goto tr_setup;
1343 }
1344 return;
1285 }
1286 return;
1345
1346 }
1347}
1348
1349static void
1287 }
1288}
1289
1290static void
1350uipaq_write_clear_stall_callback(struct usb2_xfer *xfer)
1351{
1352 struct uipaq_softc *sc = xfer->priv_sc;
1353 struct usb2_xfer *xfer_other = sc->sc_xfer[UIPAQ_BULK_DT_WR];
1354
1355 if (usb2_clear_stall_callback(xfer, xfer_other)) {
1356 DPRINTF("stall cleared\n");
1357 sc->sc_flag &= ~UIPAQ_FLAG_WRITE_STALL;
1358 usb2_transfer_start(xfer_other);
1359 }
1360}
1361
1362static void
1363uipaq_read_callback(struct usb2_xfer *xfer)
1364{
1365 struct uipaq_softc *sc = xfer->priv_sc;
1366
1367 switch (USB_GET_STATE(xfer)) {
1368 case USB_ST_TRANSFERRED:
1369 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0,
1370 xfer->actlen);
1371
1372 case USB_ST_SETUP:
1291uipaq_read_callback(struct usb2_xfer *xfer)
1292{
1293 struct uipaq_softc *sc = xfer->priv_sc;
1294
1295 switch (USB_GET_STATE(xfer)) {
1296 case USB_ST_TRANSFERRED:
1297 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0,
1298 xfer->actlen);
1299
1300 case USB_ST_SETUP:
1373 if (sc->sc_flag & UIPAQ_FLAG_READ_STALL) {
1374 usb2_transfer_start(sc->sc_xfer[UIPAQ_BULK_CS_RD]);
1375 } else {
1376 xfer->frlengths[0] = xfer->max_data_length;
1377 usb2_start_hardware(xfer);
1378 }
1301tr_setup:
1302 xfer->frlengths[0] = xfer->max_data_length;
1303 usb2_start_hardware(xfer);
1379 return;
1380
1381 default: /* Error */
1382 if (xfer->error != USB_ERR_CANCELLED) {
1304 return;
1305
1306 default: /* Error */
1307 if (xfer->error != USB_ERR_CANCELLED) {
1383 sc->sc_flag |= UIPAQ_FLAG_READ_STALL;
1384 usb2_transfer_start(sc->sc_xfer[UIPAQ_BULK_CS_RD]);
1308 /* try to clear stall first */
1309 xfer->flags.stall_pipe = 1;
1310 goto tr_setup;
1385 }
1386 return;
1387 }
1388}
1311 }
1312 return;
1313 }
1314}
1389
1390static void
1391uipaq_read_clear_stall_callback(struct usb2_xfer *xfer)
1392{
1393 struct uipaq_softc *sc = xfer->priv_sc;
1394 struct usb2_xfer *xfer_other = sc->sc_xfer[UIPAQ_BULK_DT_RD];
1395
1396 if (usb2_clear_stall_callback(xfer, xfer_other)) {
1397 DPRINTF("stall cleared\n");
1398 sc->sc_flag &= ~UIPAQ_FLAG_READ_STALL;
1399 usb2_transfer_start(xfer_other);
1400 }
1401}