static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) { char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; char result[64]; return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, sizeof(result), 0); }
static int digitv_ctrl_msg(struct dvb_usb_device *d, u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { struct digitv_state *st = d->priv; int ret, wo; wo = (rbuf == NULL || rlen == 0); /* write-only */ if (wlen > 4 || rlen > 4) return -EIO; memset(st->sndbuf, 0, 7); memset(st->rcvbuf, 0, 7); st->sndbuf[0] = cmd; st->sndbuf[1] = vv; st->sndbuf[2] = wo ? wlen : rlen; if (wo) { memcpy(&st->sndbuf[3], wbuf, wlen); ret = dvb_usb_generic_write(d, st->sndbuf, 7); } else { ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10); memcpy(rbuf, &st->rcvbuf[3], rlen); } return ret; }
static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { struct ttusb2_state *st = d->priv; u8 s[wlen+4],r[64] = { 0 }; int ret = 0; memset(s,0,wlen+4); s[0] = 0xaa; s[1] = ++st->id; s[2] = cmd; s[3] = wlen; memcpy(&s[4],wbuf,wlen); ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); if (ret != 0 || r[0] != 0x55 || r[1] != s[1] || r[2] != cmd || (rlen > 0 && r[3] != rlen)) { warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); return -EIO; } if (rlen > 0) memcpy(rbuf, &r[4], rlen); return 0; }
static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_set_parameters_msg param; char result[2]; int err; param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; param.tps = cpu_to_le16(compute_tps(fep)); param.freq = cpu_to_le32(fep->frequency / 1000); param.flags = 0; switch (fep->bandwidth_hz) { default: case 8000000: param.bandwidth = 8; break; case 7000000: param.bandwidth = 7; break; case 6000000: param.bandwidth = 6; break; } err = dvb_usb_generic_rw(state->d, (char *)¶m, sizeof(param), result, sizeof(result), 0); if (err < 0) err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); return (err < 0) ? err : 0; }
int lme2510_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { //struct lme2510_state *st = d->priv; u8 s[wlen+1], r[rlen]; int ret = 0; memset(s, 0, wlen+1); memset(r, 0, rlen); s[0] = cmd; memcpy(&s[1], wbuf, wlen); //ret = dvb_usb_generic_rw(d, s, wlen+1, r, rlen, 0); ret = dvb_usb_generic_rw(d, s, wlen+1, r, rlen, 0); if (ret != 0 ) { warn("there might have been an error during " "control message transfer. (rlen = %d)",rlen); return -EIO; } if (rlen > 0) memcpy(rbuf, &r[0], rlen); return 0; }
static int cinergyt2_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg result; u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; int ret; ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, sizeof(result), 0); if (ret < 0) return ret; *status = 0; if (0xffff - le16_to_cpu(result.gain) > 30) *status |= FE_HAS_SIGNAL; if (result.lock_bits & (1 << 6)) *status |= FE_HAS_LOCK; if (result.lock_bits & (1 << 5)) *status |= FE_HAS_SYNC; if (result.lock_bits & (1 << 4)) *status |= FE_HAS_CARRIER; if (result.lock_bits & (1 << 1)) *status |= FE_HAS_VITERBI; if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) *status &= ~FE_HAS_LOCK; return 0; }
int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { u8 *buf; int ret; buf = kmalloc(5, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = DIBUSB_REQ_POLL_REMOTE; ret = dvb_usb_generic_rw(d, buf, 1, buf, 5, 0); if (ret < 0) goto ret; dvb_usb_nec_rc_key_to_event(d, buf, event, state); if (buf[0] != 0) deb_info("key: %*ph\n", 5, buf); kfree(buf); ret: return ret; }
static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg *status; char *cmd; int ret; cmd = kmalloc(1, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; status = kmalloc(sizeof(*status), GFP_KERNEL); if (status == NULL) { kfree(cmd); return -ENOMEM; } cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS; ret = dvb_usb_generic_rw(state->d, cmd, 1, (char *)status, sizeof(*status), 0); if (ret < 0) { err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); goto out; } *snr = (status->snr << 8) | status->snr; out: kfree(cmd); kfree(status); return ret; }
static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg *status; u8 *cmd; int ret; cmd = kmalloc(1, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; status = kmalloc(sizeof(*status), GFP_KERNEL); if (status == NULL) { kfree(cmd); return -ENOMEM; } cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS; ret = dvb_usb_generic_rw(state->d, cmd, 1, (u8 *)status, sizeof(*status), 0); if (ret < 0) { err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", ret); goto out; } *unc = le32_to_cpu(status->uncorrected_block_count); out: kfree(cmd); kfree(status); return ret; }
static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg *status; char *cmd; int ret; cmd = kmalloc(1, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; status = kmalloc(sizeof(*status), GFP_KERNEL); if (status == NULL) { kfree(cmd); return -ENOMEM; } cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS; ret = dvb_usb_generic_rw(state->d, cmd, 1, (char *)status, sizeof(*status), 0); if (ret < 0) goto out; *ber = le32_to_cpu(status->viterbi_error_rate); out: kfree(cmd); kfree(status); return 0; }
static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) { struct cinergyt2_state *st = d->priv; int ret; mutex_lock(&st->data_mutex); st->data[0] = CINERGYT2_EP1_SLEEP_MODE; st->data[1] = enable ? 0 : 1; ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0); mutex_unlock(&st->data_mutex); return ret; }
static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) { struct dvb_usb_device *d = adap->dev; struct cinergyt2_state *st = d->priv; int ret; mutex_lock(&st->data_mutex); st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER; st->data[1] = enable ? 1 : 0; ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0); mutex_unlock(&st->data_mutex); return ret; }
static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg status; char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; int ret; ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, sizeof(status), 0); if (ret < 0) return ret; *ber = le32_to_cpu(status.viterbi_error_rate); return 0; }
static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg status; char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; int ret; ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, sizeof(status), 0); if (ret < 0) { err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); return ret; } *snr = (status.snr << 8) | status.snr; return 0; }
static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { struct cinergyt2_state *st = d->priv; int i, ret; *state = REMOTE_NO_KEY_PRESSED; mutex_lock(&st->data_mutex); st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS; ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0); if (ret < 0) goto ret; if (st->data[4] == 0xff) { /* key repeat */ st->rc_counter++; if (st->rc_counter > RC_REPEAT_DELAY) { for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { if (d->last_event == repeatable_keys[i]) { *state = REMOTE_KEY_REPEAT; *event = d->last_event; deb_rc("repeat key, event %x\n", *event); goto ret; } } deb_rc("repeated key (non repeatable)\n"); } goto ret; } /* hack to pass checksum on the custom field */ st->data[2] = ~st->data[1]; dvb_usb_nec_rc_key_to_event(d, st->data, event, state); if (st->data[0] != 0) { if (*event != d->last_event) st->rc_counter = 0; deb_rc("key: %*ph\n", 5, st->data); } ret: mutex_unlock(&st->data_mutex); return ret; }
static int cinergyt2_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg *result; u8 *cmd; int ret; cmd = kmalloc(1, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; result = kmalloc(sizeof(*result), GFP_KERNEL); if (result == NULL) { kfree(cmd); return -ENOMEM; } cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS; ret = dvb_usb_generic_rw(state->d, cmd, 1, (u8 *)result, sizeof(*result), 0); if (ret < 0) goto out; *status = 0; if (0xffff - le16_to_cpu(result->gain) > 30) *status |= FE_HAS_SIGNAL; if (result->lock_bits & (1 << 6)) *status |= FE_HAS_LOCK; if (result->lock_bits & (1 << 5)) *status |= FE_HAS_SYNC; if (result->lock_bits & (1 << 4)) *status |= FE_HAS_CARRIER; if (result->lock_bits & (1 << 1)) *status |= FE_HAS_VITERBI; if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) *status &= ~FE_HAS_LOCK; out: kfree(cmd); kfree(result); return ret; }
static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg status; u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; int ret; ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, sizeof(status), 0); if (ret < 0) { err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", ret); return ret; } *unc = le32_to_cpu(status.uncorrected_block_count); return 0; }
static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_set_parameters_msg *param; char *result; int err; result = kmalloc(2, GFP_KERNEL); if (result == NULL) return -ENOMEM; param = kmalloc(sizeof(*param), GFP_KERNEL); if (param == NULL) { kfree(result); return -ENOMEM; } param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; param->tps = cpu_to_le16(compute_tps(fep)); param->freq = cpu_to_le32(fep->frequency / 1000); param->flags = 0; switch (fep->bandwidth_hz) { default: case 8000000: param->bandwidth = 8; break; case 7000000: param->bandwidth = 7; break; case 6000000: param->bandwidth = 6; break; } err = dvb_usb_generic_rw(state->d, (char *)param, sizeof(*param), result, 2, 0); if (err < 0) err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); kfree(result); kfree(param); return err; }
static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_get_status_msg status; char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; int ret; ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, sizeof(status), 0); if (ret < 0) { err("cinergyt2_fe_read_signal_strength() Failed!" " (Error=%d)\n", ret); return ret; } *strength = (0xffff - le16_to_cpu(status.gain)); return 0; }
static int digitv_ctrl_msg(struct dvb_usb_device *d, u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 sndbuf[7],rcvbuf[7]; memset(sndbuf,0,7); memset(rcvbuf,0,7); sndbuf[0] = cmd; sndbuf[1] = vv; sndbuf[2] = wo ? wlen : rlen; if (!wo) { memcpy(&sndbuf[3],wbuf,wlen); dvb_usb_generic_write(d,sndbuf,7); } else { dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10); memcpy(rbuf,&rcvbuf[3],rlen); } return 0; }
static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) { char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; char state[3]; int ret; adap->fe = cinergyt2_fe_attach(adap->dev); ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, sizeof(state), 0); if (ret < 0) { deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " "state info\n"); } /* Copy this pointer as we are gonna need it in the release phase */ cinergyt2_usb_device = adap->dev; return 0; }
static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) { struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_set_parameters_msg param; char result[2]; int err; param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; param.tps = cpu_to_le16(compute_tps(fep)); param.freq = cpu_to_le32(fep->frequency / 1000); param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; err = dvb_usb_generic_rw(state->d, (char *)¶m, sizeof(param), result, sizeof(result), 0); if (err < 0) err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); return (err < 0) ? err : 0; }
static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { struct anysee_state *state = d->priv; int act_len, ret; u8 buf[64]; if (slen > sizeof(buf)) slen = sizeof(buf); memcpy(&buf[0], sbuf, slen); buf[60] = state->seq++; if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) return -EAGAIN; /* We need receive one message more after dvb_usb_generic_rw due to weird transaction flow, which is 1 x send + 2 x receive. */ ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); if (!ret) { /* receive 2nd answer */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), &act_len, 2000); if (ret) err("%s: recv bulk message failed: %d", __func__, ret); else { deb_xfer("<<< "); debug_dump(buf, act_len, deb_xfer); } } /* read request, copy returned data to return buf */ if (!ret && rbuf && rlen) memcpy(rbuf, buf, rlen); mutex_unlock(&anysee_usb_mutex); return ret; }
static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap->dev; struct cinergyt2_state *st = d->priv; int ret; adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev); mutex_lock(&st->data_mutex); st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION; ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0); if (ret < 0) { deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep state info\n"); } mutex_unlock(&st->data_mutex); /* Copy this pointer as we are gonna need it in the release phase */ cinergyt2_usb_device = adap->dev; return ret; }
static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { struct anysee_state *state = d->priv; int act_len, ret; u8 buf[64]; if (slen > sizeof(buf)) slen = sizeof(buf); memcpy(&buf[0], sbuf, slen); buf[60] = state->seq++; if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) return -EAGAIN; ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); if (!ret) { ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), &act_len, 2000); if (ret) err("%s: recv bulk message failed: %d", __func__, ret); else { deb_xfer("<<< "); debug_dump(buf, act_len, deb_xfer); } } if (!ret && rbuf && rlen) memcpy(rbuf, buf, rlen); mutex_unlock(&anysee_usb_mutex); return ret; }
static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { struct cinergyt2_state *st = d->priv; u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; int i; *state = REMOTE_NO_KEY_PRESSED; dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); if (key[4] == 0xff) { /* key repeat */ st->rc_counter++; if (st->rc_counter > RC_REPEAT_DELAY) { for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { if (d->last_event == repeatable_keys[i]) { *state = REMOTE_KEY_REPEAT; *event = d->last_event; deb_rc("repeat key, event %x\n", *event); return 0; } } deb_rc("repeated key (non repeatable)\n"); } return 0; } /* hack to pass checksum on the custom field */ key[2] = ~key[1]; dvb_usb_nec_rc_key_to_event(d, key, event, state); if (key[0] != 0) { if (*event != d->last_event) st->rc_counter = 0; deb_rc("key: %x %x %x %x %x\n", key[0], key[1], key[2], key[3], key[4]); } return 0; }
static int cinergyt2_fe_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct cinergyt2_fe_state *state = fe->demodulator_priv; int ret; mutex_lock(&state->data_mutex); state->data[0] = CINERGYT2_EP1_GET_TUNER_STATUS; ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, sizeof(state->status), 0); if (!ret) memcpy(&state->status, state->data, sizeof(state->status)); mutex_unlock(&state->data_mutex); if (ret < 0) return ret; *status = 0; if (0xffff - le16_to_cpu(state->status.gain) > 30) *status |= FE_HAS_SIGNAL; if (state->status.lock_bits & (1 << 6)) *status |= FE_HAS_LOCK; if (state->status.lock_bits & (1 << 5)) *status |= FE_HAS_SYNC; if (state->status.lock_bits & (1 << 4)) *status |= FE_HAS_CARRIER; if (state->status.lock_bits & (1 << 1)) *status |= FE_HAS_VITERBI; if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) *status &= ~FE_HAS_LOCK; return 0; }
static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct cinergyt2_fe_state *state = fe->demodulator_priv; struct dvbt_set_parameters_msg *param; int err; mutex_lock(&state->data_mutex); param = (void *)state->data; param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; param->tps = cpu_to_le16(compute_tps(fep)); param->freq = cpu_to_le32(fep->frequency / 1000); param->flags = 0; switch (fep->bandwidth_hz) { default: case 8000000: param->bandwidth = 8; break; case 7000000: param->bandwidth = 7; break; case 6000000: param->bandwidth = 6; break; } err = dvb_usb_generic_rw(state->d, state->data, sizeof(*param), state->data, 2, 0); if (err < 0) err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); mutex_unlock(&state->data_mutex); return (err < 0) ? err : 0; }
int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) { return dvb_usb_generic_rw(d,buf,len,NULL,0,0); }
warn("i2c wr: len=%d is too big!\n", wlen); ret = -EOPNOTSUPP; goto ret; } sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; sndbuf[1] = (addr << 1) | (wo ? 0 : 1); memcpy(&sndbuf[2], wbuf, wlen); if (!wo) { sndbuf[wlen + 2] = (rlen >> 8) & 0xff; sndbuf[wlen + 3] = rlen & 0xff; } ret = dvb_usb_generic_rw(d, sndbuf, len, rbuf, rlen, 0); ret: kfree(sndbuf); return ret; } /* * I2C master xfer function */ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; if (mutex_lock_interruptible(&d->i2c_mutex) < 0)