static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) { u8 b; if ((end - start) <= 0) return NULL; b = *start++; item->type = (b >> 2) & 3; item->tag = (b >> 4) & 15; if (item->tag == HID_ITEM_TAG_LONG) { item->format = HID_ITEM_FORMAT_LONG; if ((end - start) < 2) return NULL; item->size = *start++; item->tag = *start++; if ((end - start) < item->size) return NULL; item->data.longdata = start; start += item->size; return start; } item->format = HID_ITEM_FORMAT_SHORT; item->size = b & 3; switch (item->size) { case 0: return start; case 1: if ((end - start) < 1) return NULL; item->data.u8 = *start++; return start; case 2: if ((end - start) < 2) return NULL; item->data.u16 = get_unaligned_le16(start); start = (__u8 *)((__le16 *)start + 1); return start; case 3: item->size++; if ((end - start) < 4) return NULL; item->data.u32 = get_unaligned_le32(start); start = (__u8 *)((__le32 *)start + 1); return start; } return NULL; }
/** * ath5k_hw_set_opmode - Set PCU operating mode * * @ah: The &struct ath5k_hw * @op_mode: &enum nl80211_iftype operating mode * * Initialize PCU for the various operating modes (AP/STA etc) */ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) { struct ath_common *common = ath5k_hw_common(ah); u32 pcu_reg, beacon_reg, low_id, high_id; ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); /* Preserve rest settings */ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE | (ah->ah_version == AR5K_AR5210 ? (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); beacon_reg = 0; switch (op_mode) { case NL80211_IFTYPE_ADHOC: pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; beacon_reg |= AR5K_BCR_ADHOC; if (ah->ah_version == AR5K_AR5210) pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; else AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; beacon_reg |= AR5K_BCR_AP; if (ah->ah_version == AR5K_AR5210) pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; else AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); break; case NL80211_IFTYPE_STATION: pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | (ah->ah_version == AR5K_AR5210 ? AR5K_STA_ID1_PWR_SV : 0); case NL80211_IFTYPE_MONITOR: pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | (ah->ah_version == AR5K_AR5210 ? AR5K_STA_ID1_NO_PSPOLL : 0); break; default: return -EINVAL; } /* * Set PCU registers */ low_id = get_unaligned_le32(common->macaddr); high_id = get_unaligned_le16(common->macaddr + 4); ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); /* * Set Beacon Control Register on 5210 */ if (ah->ah_version == AR5K_AR5210) ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); return 0; }
static void silead_ts_read_data(struct i2c_client *client) { struct silead_ts_data *data = i2c_get_clientdata(client); struct input_dev *input = data->input; struct device *dev = &client->dev; u8 *bufp, buf[SILEAD_TS_DATA_LEN]; int touch_nr, softbutton, error, i; bool softbutton_pressed = false; error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA, SILEAD_TS_DATA_LEN, buf); if (error < 0) { dev_err(dev, "Data read error %d\n", error); return; } if (buf[0] > data->max_fingers) { dev_warn(dev, "More touches reported then supported %d > %d\n", buf[0], data->max_fingers); buf[0] = data->max_fingers; } touch_nr = 0; bufp = buf + SILEAD_POINT_DATA_LEN; for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) { softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] & SILEAD_EXTRA_DATA_MASK) >> 4; if (softbutton) { /* * For now only respond to softbutton == 0x01, some * tablets *without* a capacative button send 0x04 * when crossing the edges of the screen. */ if (softbutton == 0x01) softbutton_pressed = true; continue; } /* * Bits 4-7 are the touch id, note not all models have * hardware touch ids so atm we don't use these. */ data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] & SILEAD_EXTRA_DATA_MASK) >> 4; touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop, get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff, get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff); touch_nr++; } input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0); for (i = 0; i < touch_nr; i++) { input_mt_slot(input, data->slots[i]); input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, data->pos[i].x); input_report_abs(input, ABS_MT_POSITION_Y, data->pos[i].y); dev_dbg(dev, "x=%d y=%d hw_id=%d sw_id=%d\n", data->pos[i].x, data->pos[i].y, data->id[i], data->slots[i]); } input_mt_sync_frame(input); input_report_key(input, KEY_LEFTMETA, softbutton_pressed); input_sync(input); }
static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard) { static const u8 null_addr[ETH_ALEN] = {}; const u8 *macaddr = dev->mt76.macaddr; u32 val; int i, k; if (!mt76x2_wait_for_mac(dev)) return -ETIMEDOUT; val = mt76_rr(dev, MT_WPDMA_GLO_CFG); val &= ~(MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_BUSY | MT_WPDMA_GLO_CFG_DMA_BURST_SIZE); val |= FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3); mt76_wr(dev, MT_WPDMA_GLO_CFG, val); mt76x2_mac_pbf_init(dev); mt76_write_mac_initvals(dev); mt76x2_fixup_xtal(dev); mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR | MT_MAC_SYS_CTRL_RESET_BBP); if (is_mt7612(dev)) mt76_clear(dev, MT_COEXCFG0, MT_COEXCFG0_COEX_EN); mt76_set(dev, MT_EXT_CCA_CFG, 0x0000f000); mt76_clear(dev, MT_TX_ALC_CFG_4, BIT(31)); mt76_wr(dev, MT_RF_BYPASS_0, 0x06000000); mt76_wr(dev, MT_RF_SETTING_0, 0x08800000); usleep_range(5000, 10000); mt76_wr(dev, MT_RF_BYPASS_0, 0x00000000); mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401); mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr)); mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4)); mt76_wr(dev, MT_MAC_BSSID_DW0, get_unaligned_le32(macaddr)); mt76_wr(dev, MT_MAC_BSSID_DW1, get_unaligned_le16(macaddr + 4) | FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 beacons */ MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); /* Fire a pre-TBTT interrupt 8 ms before TBTT */ mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, 8 << 4); mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, MT_DFS_GP_INTERVAL); mt76_wr(dev, MT_INT_TIMER_EN, 0); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); if (!hard) return 0; for (i = 0; i < 256 / 32; i++) mt76_wr(dev, MT_WCID_DROP_BASE + i * 4, 0); for (i = 0; i < 256; i++) mt76x2_mac_wcid_setup(dev, i, 0, NULL); for (i = 0; i < MT_MAX_VIFS; i++) mt76x2_mac_wcid_setup(dev, MT_VIF_WCID(i), i, NULL); for (i = 0; i < 16; i++) for (k = 0; k < 4; k++) mt76x2_mac_shared_key_setup(dev, i, k, NULL); for (i = 0; i < 8; i++) { mt76x2_mac_set_bssid(dev, i, null_addr); mt76x2_mac_set_beacon(dev, i, NULL); } for (i = 0; i < 16; i++) mt76_rr(dev, MT_TX_STAT_FIFO); mt76_wr(dev, MT_CH_TIME_CFG, MT_CH_TIME_CFG_TIMER_EN | MT_CH_TIME_CFG_TX_AS_BUSY | MT_CH_TIME_CFG_RX_AS_BUSY | MT_CH_TIME_CFG_NAV_AS_BUSY | MT_CH_TIME_CFG_EIFS_AS_BUSY | FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1)); mt76x2_init_beacon_offsets(dev); mt76x2_set_tx_ackto(dev); return 0; }
static int nokia_setup_fw(struct hci_uart *hu) { struct nokia_bt_dev *btdev = hu->priv; struct device *dev = &btdev->serdev->dev; const char *fwname; const struct firmware *fw; const u8 *fw_ptr; size_t fw_size; int err; dev_dbg(dev, "setup firmware"); if (btdev->man_id == NOKIA_ID_BCM2048) { fwname = FIRMWARE_BCM2048; } else if (btdev->man_id == NOKIA_ID_TI1271) { fwname = FIRMWARE_TI1271; } else { dev_err(dev, "Unsupported bluetooth device!"); return -ENODEV; } err = request_firmware(&fw, fwname, dev); if (err < 0) { dev_err(dev, "%s: Failed to load Nokia firmware file (%d)", hu->hdev->name, err); return err; } fw_ptr = fw->data; fw_size = fw->size; while (fw_size >= 4) { u16 pkt_size = get_unaligned_le16(fw_ptr); u8 pkt_type = fw_ptr[2]; const struct hci_command_hdr *cmd; u16 opcode; struct sk_buff *skb; switch (pkt_type) { case HCI_COMMAND_PKT: cmd = (struct hci_command_hdr *)(fw_ptr + 3); opcode = le16_to_cpu(cmd->opcode); skb = __hci_cmd_sync(hu->hdev, opcode, cmd->plen, fw_ptr + 3 + HCI_COMMAND_HDR_SIZE, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { err = PTR_ERR(skb); dev_err(dev, "%s: FW command %04x failed (%d)", hu->hdev->name, opcode, err); goto done; } kfree_skb(skb); break; case HCI_NOKIA_RADIO_PKT: case HCI_NOKIA_NEG_PKT: case HCI_NOKIA_ALIVE_PKT: break; } fw_ptr += pkt_size + 2; fw_size -= pkt_size + 2; } done: release_firmware(fw); return err; }
static uint16_t r2le(const uint16_t *x) { return get_unaligned_le16(x); }
static void gtco_urb_callback(struct urb *urbinfo) { struct gtco *device = urbinfo->context; struct input_dev *inputdev; int rc; u32 val = 0; s8 valsigned = 0; char le_buffer[2]; inputdev = device->inputdevice; if (urbinfo->status == -ECONNRESET || urbinfo->status == -ENOENT || urbinfo->status == -ESHUTDOWN) { return; } if (urbinfo->status != 0) { goto resubmit; } if (inputdev->id.product == PID_1000 || inputdev->id.product == PID_1001 || inputdev->id.product == PID_1002) { switch (device->buffer[0]) { case 5: val = ((u16)(device->buffer[8]) << 1); val |= (u16)(device->buffer[7] >> 7); input_report_abs(inputdev, ABS_PRESSURE, device->buffer[8]); device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); case 4: if (device->buffer[6] & 0x40) device->buffer[6] |= 0x80; if (device->buffer[7] & 0x40) device->buffer[7] |= 0x80; valsigned = (device->buffer[6]); input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned); valsigned = (device->buffer[7]); input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned); case 2: case 3: val = (device->buffer[5]) & MASK_BUTTON; input_event(inputdev, EV_MSC, MSC_SERIAL, val); case 1: val = get_unaligned_le16(&device->buffer[1]); input_report_abs(inputdev, ABS_X, val); val = get_unaligned_le16(&device->buffer[3]); input_report_abs(inputdev, ABS_Y, val); val = device->buffer[5] & MASK_INRANGE ? 1 : 0; input_report_abs(inputdev, ABS_DISTANCE, val); if (device->buffer[0] == 1) { val = device->buffer[5] & MASK_BUTTON; dbg("======>>>>>>REPORT 1: val 0x%X(%d)", val, val); input_event(inputdev, EV_MSC, MSC_SERIAL, val); } break; case 7: input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); break; } } if (inputdev->id.product == PID_400 || inputdev->id.product == PID_401) { if (device->buffer[0] == 2) { input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); } if (device->buffer[0] == 1) { char buttonbyte; if (device->max_X > 0x10000) { val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]); val |= (u32)(((u8)device->buffer[3] & 0x1) << 16); input_report_abs(inputdev, ABS_X, val); le_buffer[0] = (u8)((u8)(device->buffer[3]) >> 1); le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7); le_buffer[1] = (u8)(device->buffer[4] >> 1); le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7); val = get_unaligned_le16(le_buffer); input_report_abs(inputdev, ABS_Y, val); buttonbyte = device->buffer[5] >> 1; } else {
static void parse_hid_report_descriptor(struct gtco *device, char * report, int length) { int x, i = 0; __u8 prefix; __u8 size; __u8 tag; __u8 type; __u8 data = 0; __u16 data16 = 0; __u32 data32 = 0; int inputnum = 0; __u32 usage = 0; __u32 globalval[TAG_GLOB_MAX]; __u32 oldval[TAG_GLOB_MAX]; char maintype = 'x'; char globtype[12]; int indent = 0; char indentstr[10] = ""; dbg("======>>>>>>PARSE<<<<<<======"); while (i < length) { prefix = report[i]; i++; size = PREF_SIZE(prefix); switch (size) { case 1: data = report[i]; break; case 2: data16 = get_unaligned_le16(&report[i]); break; case 3: size = 4; data32 = get_unaligned_le32(&report[i]); break; } i += size; tag = PREF_TAG(prefix); type = PREF_TYPE(prefix); switch (type) { case TYPE_MAIN: strcpy(globtype, ""); switch (tag) { case TAG_MAIN_INPUT: maintype = 'I'; if (data == 2) strcpy(globtype, "Variable"); else if (data == 3) strcpy(globtype, "Var|Const"); dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits", globalval[TAG_GLOB_REPORT_ID], inputnum, globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]); switch (inputnum) { case 0: dbg("GER: X Usage: 0x%x", usage); if (device->max_X == 0) { device->max_X = globalval[TAG_GLOB_LOG_MAX]; device->min_X = globalval[TAG_GLOB_LOG_MIN]; } break; case 1: dbg("GER: Y Usage: 0x%x", usage); if (device->max_Y == 0) { device->max_Y = globalval[TAG_GLOB_LOG_MAX]; device->min_Y = globalval[TAG_GLOB_LOG_MIN]; } break; default: if (usage == DIGITIZER_USAGE_TILT_X) { if (device->maxtilt_X == 0) { device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; } } if (usage == DIGITIZER_USAGE_TILT_Y) { if (device->maxtilt_Y == 0) { device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; } } if (usage == DIGITIZER_USAGE_TIP_PRESSURE) { if (device->maxpressure == 0) { device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; device->minpressure = globalval[TAG_GLOB_LOG_MIN]; } } break; } inputnum++; break; case TAG_MAIN_OUTPUT: maintype = 'O'; break; case TAG_MAIN_FEATURE: maintype = 'F'; break; case TAG_MAIN_COL_START: maintype = 'S'; if (data == 0) { dbg("======>>>>>> Physical"); strcpy(globtype, "Physical"); } else dbg("======>>>>>>"); indent++; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; for (x = 0; x < TAG_GLOB_MAX; x++) oldval[x] = globalval[x]; break; case TAG_MAIN_COL_END: dbg("<<<<<<======"); maintype = 'E'; indent--; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; for (x = 0; x < TAG_GLOB_MAX; x++) globalval[x] = oldval[x]; break; } switch (size) { case 1: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data); break; case 2: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data16); break; case 4: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data32); break; } break; case TYPE_GLOBAL: switch (tag) { case TAG_GLOB_USAGE: if (device->usage == 0) device->usage = data; strcpy(globtype, "USAGE"); break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "LOG_MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "LOG_MAX"); break; case TAG_GLOB_PHYS_MIN: strcpy(globtype, "PHYS_MIN"); break; case TAG_GLOB_PHYS_MAX: strcpy(globtype, "PHYS_MAX"); break; case TAG_GLOB_UNIT_EXP: strcpy(globtype, "EXP"); break; case TAG_GLOB_UNIT: strcpy(globtype, "UNIT"); break; case TAG_GLOB_REPORT_SZ: strcpy(globtype, "REPORT_SZ"); break; case TAG_GLOB_REPORT_ID: strcpy(globtype, "REPORT_ID"); inputnum = 0; break; case TAG_GLOB_REPORT_CNT: strcpy(globtype, "REPORT_CNT"); break; case TAG_GLOB_PUSH: strcpy(globtype, "PUSH"); break; case TAG_GLOB_POP: strcpy(globtype, "POP"); break; } if (tag < TAG_GLOB_MAX) { switch (size) { case 1: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data); globalval[tag] = data; break; case 2: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data16); globalval[tag] = data16; break; case 4: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data32); globalval[tag] = data32; break; } } else { dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ", indentstr, tag, size); } break; case TYPE_LOCAL: switch (tag) { case TAG_GLOB_USAGE: strcpy(globtype, "USAGE"); usage = data; break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "MAX"); break; default: strcpy(globtype, "UNKNOWN"); break; } switch (size) { case 1: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data); break; case 2: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data16); break; case 4: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data32); break; } break; } } }
static u16 nouveau_bios_rd16(struct nouveau_object *object, u64 addr) { struct nouveau_bios *bios = (void *)object; return get_unaligned_le16(&bios->data[addr]); }
static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, struct wacom_features *features) { struct usb_device *dev = interface_to_usbdev(intf); char limit = 0; /* */ int result = 0; int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; unsigned char *report; report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); if (!report) return -ENOMEM; /* */ do { result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, HID_DEVICET_REPORT << 8, intf->altsetting[0].desc.bInterfaceNumber, /* */ report, hid_desc->wDescriptorLength, 5000); /* */ } while (result < 0 && limit++ < WAC_MSG_RETRIES); /* */ if (result < 0) goto out; for (i = 0; i < hid_desc->wDescriptorLength; i++) { switch (report[i]) { case HID_USAGE_PAGE: switch (report[i + 1]) { case HID_USAGE_PAGE_DIGITIZER: usage = WCM_DIGITIZER; i++; break; case HID_USAGE_PAGE_DESKTOP: usage = WCM_DESKTOP; i++; break; } break; case HID_USAGE: switch (report[i + 1]) { case HID_USAGE_X: if (usage == WCM_DESKTOP) { if (finger) { features->device_type = BTN_TOOL_FINGER; if (features->type == TABLETPC2FG) { /* */ features->pktlen = WACOM_PKGLEN_TPC2FG; } if (features->type == BAMBOO_PT) { /* */ features->pktlen = WACOM_PKGLEN_BBTOUCH; features->x_phy = get_unaligned_le16(&report[i + 5]); features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; } else { features->x_max = get_unaligned_le16(&report[i + 3]); features->x_phy = get_unaligned_le16(&report[i + 6]); features->unit = report[i + 9]; features->unitExpo = report[i + 11]; i += 12; } } else if (pen) { /* */ if (features->type == TABLETPC2FG) features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = get_unaligned_le16(&report[i + 3]); i += 4; } } break; case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { features->device_type = BTN_TOOL_FINGER; if (features->type == TABLETPC2FG) { /* */ features->pktlen = WACOM_PKGLEN_TPC2FG; features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; } else if (features->type == BAMBOO_PT) { /* */ features->pktlen = WACOM_PKGLEN_BBTOUCH; features->y_phy = get_unaligned_le16(&report[i + 3]); features->y_max = get_unaligned_le16(&report[i + 6]); i += 12; } else { features->y_max = features->x_max; features->y_phy = get_unaligned_le16(&report[i + 3]); i += 4; } } else if (pen) { /* */ if (features->type == TABLETPC2FG) features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->y_max = get_unaligned_le16(&report[i + 3]); i += 4; } } break; case HID_USAGE_FINGER: finger = 1; i++; break; /* */ case HID_USAGE_STYLUS: pen = 1; i++; break; } break; case HID_COLLECTION_END: /* */ finger = usage = 0; break; case HID_COLLECTION: i++; switch (report[i]) { case HID_COLLECTION_LOGICAL: i += wacom_parse_logical_collection(&report[i], features); break; } break; } } out: result = 0; kfree(report); return result; }
/* control interface reports status changes with "interrupt" transfers */ static void acm_ctrl_irq(struct urb *urb) { struct acm *acm = urb->context; struct usb_cdc_notification *dr = urb->transfer_buffer; struct tty_struct *tty; unsigned char *data; int newctrl; int retval; int status = urb->status; switch (status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dev_dbg(&acm->control->dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: dev_dbg(&acm->control->dev, "%s - nonzero urb status received: %d\n", __func__, status); goto exit; } usb_mark_last_busy(acm->dev); data = (unsigned char *)(dr + 1); switch (dr->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: dev_dbg(&acm->control->dev, "%s - network connection: %d\n", __func__, dr->wValue); break; case USB_CDC_NOTIFY_SERIAL_STATE: tty = tty_port_tty_get(&acm->port); newctrl = get_unaligned_le16(data); if (tty) { if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { dev_dbg(&acm->control->dev, "%s - calling hangup\n", __func__); tty_hangup(tty); } tty_kref_put(tty); } acm->ctrlin = newctrl; dev_dbg(&acm->control->dev, "%s - input control lines: dcd%c dsr%c break%c " "ring%c framing%c parity%c overrun%c\n", __func__, acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-', acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); break; default: dev_dbg(&acm->control->dev, "%s - unknown notification %d received: index %d " "len %d data0 %d data1 %d\n", __func__, dr->bNotificationType, dr->wIndex, dr->wLength, data[0], data[1]); break; } exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n", __func__, retval); }
int btbcm_setup_patchram(struct hci_dev *hdev) { char fw_name[64]; const struct firmware *fw; u16 subver, rev, pid, vid; const char *hw_name = NULL; struct sk_buff *skb; struct hci_rp_read_local_version *ver; int i, err; /* Reset */ err = btbcm_reset(hdev); if (err) return err; /* Read Local Version Info */ skb = btbcm_read_local_version(hdev); if (IS_ERR(skb)) return PTR_ERR(skb); ver = (struct hci_rp_read_local_version *)skb->data; rev = le16_to_cpu(ver->hci_rev); subver = le16_to_cpu(ver->lmp_subver); kfree_skb(skb); /* Read Verbose Config Version Info */ skb = btbcm_read_verbose_config(hdev); if (IS_ERR(skb)) return PTR_ERR(skb); BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); kfree_skb(skb); /* Read Local Name */ skb = btbcm_read_local_name(hdev); if (IS_ERR(skb)) return PTR_ERR(skb); BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); kfree_skb(skb); switch ((rev & 0xf000) >> 12) { case 0: case 3: for (i = 0; bcm_uart_subver_table[i].name; i++) { if (subver == bcm_uart_subver_table[i].subver) { hw_name = bcm_uart_subver_table[i].name; break; } } snprintf(fw_name, sizeof(fw_name), "brcm/%s.hcd", hw_name ? : "BCM"); break; case 1: case 2: /* Read USB Product Info */ skb = btbcm_read_usb_product(hdev); if (IS_ERR(skb)) return PTR_ERR(skb); vid = get_unaligned_le16(skb->data + 1); pid = get_unaligned_le16(skb->data + 3); kfree_skb(skb); for (i = 0; bcm_usb_subver_table[i].name; i++) { if (subver == bcm_usb_subver_table[i].subver) { hw_name = bcm_usb_subver_table[i].name; break; } } snprintf(fw_name, sizeof(fw_name), "brcm/%s-%4.4x-%4.4x.hcd", hw_name ? : "BCM", vid, pid); break; default: return 0; } BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, hw_name ? : "BCM", (subver & 0xe000) >> 13, (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); err = request_firmware(&fw, fw_name, &hdev->dev); if (err < 0) { BT_INFO("%s: BCM: Patch %s not found", hdev->name, fw_name); goto done; } btbcm_patchram(hdev, fw); release_firmware(fw); /* Reset */ err = btbcm_reset(hdev); if (err) return err; /* Read Local Version Info */ skb = btbcm_read_local_version(hdev); if (IS_ERR(skb)) return PTR_ERR(skb); ver = (struct hci_rp_read_local_version *)skb->data; rev = le16_to_cpu(ver->hci_rev); subver = le16_to_cpu(ver->lmp_subver); kfree_skb(skb); BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, hw_name ? : "BCM", (subver & 0xe000) >> 13, (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); /* Read Local Name */ skb = btbcm_read_local_name(hdev); if (IS_ERR(skb)) return PTR_ERR(skb); BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); kfree_skb(skb); done: btbcm_check_bdaddr(hdev); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); return 0; }
int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) { int ret = _SUCCESS; u8 *p; u8 *pHT_caps_ie = NULL; u8 *pHT_info_ie = NULL; struct sta_info *psta = NULL; u16 cap, ht_cap = false; uint ie_len = 0; int group_cipher, pairwise_cipher; u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; int supportRateNum = 0; u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01}; u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; struct registry_priv *pregistrypriv = &padapter->registrypriv; struct security_priv *psecuritypriv = &padapter->securitypriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; u8 *ie = pbss_network->ies; /* SSID */ /* Supported rates */ /* DS Params */ /* WLAN_EID_COUNTRY */ /* ERP Information element */ /* Extended supported rates */ /* WPA/WPA2 */ /* Wi-Fi Wireless Multimedia Extensions */ /* ht_capab, ht_oper */ /* WPS IE */ DBG_88E("%s, len =%d\n", __func__, len); if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return _FAIL; if (len < 0 || len > MAX_IE_SZ) return _FAIL; pbss_network->ie_length = len; memset(ie, 0, MAX_IE_SZ); memcpy(ie, pbuf, pbss_network->ie_length); if (pbss_network->InfrastructureMode != Ndis802_11APMode) return _FAIL; pbss_network->Rssi = 0; ether_addr_copy(pbss_network->MacAddress, myid(&padapter->eeprompriv)); /* beacon interval */ p = rtw_get_beacon_interval_from_ie(ie);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */ pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p); /* capability */ cap = get_unaligned_le16(ie); /* SSID */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid)); memcpy(pbss_network->ssid.ssid, (p + 2), ie_len); pbss_network->ssid.ssid_length = ie_len; } /* channel */ channel = 0; pbss_network->Configuration.Length = 0; p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) channel = *(p + 2); pbss_network->Configuration.DSConfig = channel; memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); /* get supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p) { memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } /* get ext_supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_); if (p) { memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } network_type = rtw_check_network_type(supportRate, supportRateNum, channel); rtw_set_supported_rate(pbss_network->SupportedRates, network_type); /* parsing ERP_IE */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) ERP_IE_handler(padapter, (struct ndis_802_11_var_ie *)p); /* update privacy/security */ if (cap & BIT(4)) pbss_network->Privacy = 1; else pbss_network->Privacy = 0; psecuritypriv->wpa_psk = 0; /* wpa2 */ group_cipher = 0; pairwise_cipher = 0; psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ psecuritypriv->wpa_psk |= BIT(1); psecuritypriv->wpa2_group_cipher = group_cipher; psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; } } /* wpa */ ie_len = 0; group_cipher = 0; pairwise_cipher = 0; psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))); if ((p) && (!memcmp(p + 2, OUI1, 4))) { if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ psecuritypriv->wpa_psk |= BIT(0); psecuritypriv->wpa_group_cipher = group_cipher; psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; } break; } if ((!p) || (ie_len == 0)) break; } /* wmm */ ie_len = 0; pmlmepriv->qospriv.qos_option = 0; if (pregistrypriv->wmm_enable) { for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))); if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) { pmlmepriv->qospriv.qos_option = 1; /* QoS Info, support U-APSD */ *(p + 8) |= BIT(7); /* disable all ACM bits since the WMM * admission control is not supported */ *(p + 10) &= ~BIT(4); /* BE */ *(p + 14) &= ~BIT(4); /* BK */ *(p + 18) &= ~BIT(4); /* VI */ *(p + 22) &= ~BIT(4); /* VO */ break; } if ((!p) || (ie_len == 0)) break; } } /* parsing HT_CAP_IE */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2); pHT_caps_ie = p; ht_cap = true; network_type |= WIRELESS_11_24N; if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2)); else pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); /* set Max Rx AMPDU size to 64K */ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); pht_cap->mcs.rx_mask[0] = 0xff; pht_cap->mcs.rx_mask[1] = 0x0; memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len); } /* parsing HT_INFO_IE */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) pHT_info_ie = p; switch (network_type) { case WIRELESS_11B: pbss_network->NetworkTypeInUse = Ndis802_11DS; break; case WIRELESS_11G: case WIRELESS_11BG: case WIRELESS_11G_24N: case WIRELESS_11BG_24N: pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; break; case WIRELESS_11A: pbss_network->NetworkTypeInUse = Ndis802_11OFDM5; break; default: pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; break; } pmlmepriv->cur_network.network_type = network_type; pmlmepriv->htpriv.ht_option = false; if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { /* todo: */ /* ht_cap = false; */ } /* ht_cap */ if (pregistrypriv->ht_enable && ht_cap) { pmlmepriv->htpriv.ht_option = true; pmlmepriv->qospriv.qos_option = 1; if (pregistrypriv->ampdu_enable == 1) pmlmepriv->htpriv.ampdu_enable = true; HT_caps_handler(padapter, (struct ndis_802_11_var_ie *)pHT_caps_ie); HT_info_handler(padapter, (struct ndis_802_11_var_ie *)pHT_info_ie); } pbss_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network); /* issue beacon to start bss network */ start_bss_network(padapter, (u8 *)pbss_network); /* alloc sta_info for ap itself */ psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress); if (!psta) { psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress); if (!psta) return _FAIL; } /* fix bug of flush_cam_entry at STOP AP mode */ psta->state |= WIFI_AP_STATE; rtw_indicate_connect(padapter); pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */ return ret; }
/* * Be careful, ELD buf could be totally rubbish! */ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, const unsigned char *buf, int size) { int mnl; int i; e->eld_ver = GRAB_BITS(buf, 0, 3, 5); if (e->eld_ver != ELD_VER_CEA_861D && e->eld_ver != ELD_VER_PARTIAL) { snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n", e->eld_ver); goto out_fail; } e->baseline_len = GRAB_BITS(buf, 2, 0, 8); mnl = GRAB_BITS(buf, 4, 0, 5); e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3); e->support_hdcp = GRAB_BITS(buf, 5, 0, 1); e->support_ai = GRAB_BITS(buf, 5, 1, 1); e->conn_type = GRAB_BITS(buf, 5, 2, 2); e->sad_count = GRAB_BITS(buf, 5, 4, 4); e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2; e->spk_alloc = GRAB_BITS(buf, 7, 0, 7); e->port_id = get_unaligned_le64(buf + 8); /* not specified, but the spec's tendency is little endian */ e->manufacture_id = get_unaligned_le16(buf + 16); e->product_id = get_unaligned_le16(buf + 18); if (mnl > ELD_MAX_MNL) { snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl); goto out_fail; } else if (ELD_FIXED_BYTES + mnl > size) { snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl); goto out_fail; } else strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); for (i = 0; i < e->sad_count; i++) { if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i); goto out_fail; } hdmi_update_short_audio_desc(e->sad + i, buf + ELD_FIXED_BYTES + mnl + 3 * i); } /* * HDMI sink's ELD info cannot always be retrieved for now, e.g. * in console or for audio devices. Assume the highest speakers * configuration, to _not_ prohibit multi-channel audio playback. */ if (!e->spk_alloc) e->spk_alloc = 0xffff; return 0; out_fail: return -EINVAL; }
static inline u32 u16_field_get(const u8 *preq_elem, int offset, bool ae) { if (ae) offset += 6; return get_unaligned_le16(preq_elem + offset); }
static int kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { /* * Our task here is to strip off framing, leaving skb with one * data frame for the usbnet framework code to process. */ const static u8 HEADER_END_OF_USB_PACKET[] = { 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 }; const static u8 EXPECTED_UNKNOWN_HEADER_1[] = { 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 }; const static u8 EXPECTED_UNKNOWN_HEADER_2[] = { 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 }; int i = 0; /* incomplete header? */ if (skb->len < KALMIA_HEADER_LENGTH) return 0; do { struct sk_buff *skb2 = NULL; u8 *header_start; u16 usb_packet_length, ether_packet_length; int is_last; header_start = skb->data; if (unlikely(header_start[0] != 0x57 || header_start[1] != 0x44)) { if (!memcmp(header_start, EXPECTED_UNKNOWN_HEADER_1, sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp( header_start, EXPECTED_UNKNOWN_HEADER_2, sizeof(EXPECTED_UNKNOWN_HEADER_2))) { netdev_dbg( dev->net, "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", header_start[0], header_start[1], header_start[2], header_start[3], header_start[4], header_start[5], skb->len - KALMIA_HEADER_LENGTH); } else { netdev_err( dev->net, "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", header_start[0], header_start[1], header_start[2], header_start[3], header_start[4], header_start[5], skb->len - KALMIA_HEADER_LENGTH); return 0; } } else netdev_dbg( dev->net, "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", header_start[0], header_start[1], header_start[2], header_start[3], header_start[4], header_start[5], skb->len - KALMIA_HEADER_LENGTH); /* subtract start header and end header */ usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); ether_packet_length = get_unaligned_le16(&header_start[2]); skb_pull(skb, KALMIA_HEADER_LENGTH); /* Some small packets misses end marker */ if (usb_packet_length < ether_packet_length) { ether_packet_length = usb_packet_length + KALMIA_HEADER_LENGTH; is_last = true; } else { netdev_dbg(dev->net, "Correct package length #%i", i + 1); is_last = (memcmp(skb->data + ether_packet_length, HEADER_END_OF_USB_PACKET, sizeof(HEADER_END_OF_USB_PACKET)) == 0); if (!is_last) { header_start = skb->data + ether_packet_length; netdev_dbg( dev->net, "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", header_start[0], header_start[1], header_start[2], header_start[3], header_start[4], header_start[5], skb->len - KALMIA_HEADER_LENGTH); } } if (is_last) { skb2 = skb; } else { skb2 = skb_clone(skb, GFP_ATOMIC); if (unlikely(!skb2)) return 0; } skb_trim(skb2, ether_packet_length); if (is_last) { return 1; } else { usbnet_skb_return(dev, skb2); skb_pull(skb, ether_packet_length); } i++; } while (skb->len); return 1; }
int ieee80211_radiotap_iterator_next( struct ieee80211_radiotap_iterator *iterator) { while (1) { int hit = 0; int pad, align, size, subns; guint32 oui; /* if no more EXT bits, that's it */ if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT && !(iterator->_bitmap_shifter & 1)) return -ENOENT; if (!(iterator->_bitmap_shifter & 1)) goto next_entry; /* arg not present */ /* get alignment/size of data */ switch (iterator->_arg_index % 32) { case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: case IEEE80211_RADIOTAP_EXT: align = 1; size = 0; break; case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: align = 2; size = 6; break; default: #ifdef RADIOTAP_SUPPORT_OVERRIDES if (find_override(iterator, &align, &size)) { /* all set */ } else #endif if (!iterator->current_namespace || iterator->_arg_index >= iterator->current_namespace->n_bits) { if (iterator->current_namespace == &radiotap_ns) return -ENOENT; align = 0; } else { align = iterator->current_namespace->align_size[iterator->_arg_index].align; size = iterator->current_namespace->align_size[iterator->_arg_index].size; } if (!align) { /* skip all subsequent data */ iterator->_arg = iterator->_next_ns_data; /* give up on this namespace */ iterator->current_namespace = NULL; goto next_entry; } break; } /* * arg is present, account for alignment padding * * Note that these alignments are relative to the start * of the radiotap header. There is no guarantee * that the radiotap header itself is aligned on any * kind of boundary. * * The above is why get_unaligned() is used to dereference * multibyte elements from the radiotap area. */ pad = (int)((iterator->_arg - (unsigned char *)iterator->_rtheader) & (align - 1)); if (pad) iterator->_arg += align - pad; if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) { int vnslen; if (!ITERATOR_VALID(iterator, size)) return -EINVAL; oui = (*iterator->_arg << 16) | (*(iterator->_arg + 1) << 8) | *(iterator->_arg + 2); subns = *(iterator->_arg + 3); find_ns(iterator, oui, subns); vnslen = get_unaligned_le16(iterator->_arg + 4); iterator->_next_ns_data = iterator->_arg + size + vnslen; if (!iterator->current_namespace) size += vnslen; } /* * this is what we will return to user, but we need to * move on first so next call has something fresh to test */ iterator->this_arg_index = iterator->_arg_index; iterator->this_arg = iterator->_arg; iterator->this_arg_size = size; /* internally move on the size of this arg */ iterator->_arg += size; /* * check for insanity where we are given a bitmap that * claims to have more arg content than the length of the * radiotap section. We will normally end up equalling this * max_length on the last arg, never exceeding it. */ if (!ITERATOR_VALID(iterator, 0)) return -EINVAL; /* these special ones are valid in each bitmap word */ switch (iterator->_arg_index % 32) { case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: iterator->_reset_on_ext = 1; iterator->is_radiotap_ns = 0; /* * If parser didn't register this vendor * namespace with us, allow it to show it * as 'raw. Do do that, set argument index * to vendor namespace. */ iterator->this_arg_index = IEEE80211_RADIOTAP_VENDOR_NAMESPACE; if (!iterator->current_namespace) hit = 1; goto next_entry; case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: iterator->_reset_on_ext = 1; iterator->current_namespace = &radiotap_ns; iterator->is_radiotap_ns = 1; goto next_entry; case IEEE80211_RADIOTAP_EXT: /* * bit 31 was set, there is more * -- move to next u32 bitmap */ iterator->_bitmap_shifter = get_unaligned_le32(iterator->_next_bitmap); iterator->_next_bitmap++; if (iterator->_reset_on_ext) iterator->_arg_index = 0; else iterator->_arg_index++; iterator->_reset_on_ext = 0; break; default: /* we've got a hit! */ hit = 1; next_entry: iterator->_bitmap_shifter >>= 1; iterator->_arg_index++; } /* if we found a valid arg earlier, return it now */ if (hit) return 0; } }
/* * Interface Descriptor of wacom devices can be incomplete and * inconsistent so wacom_features table is used to store stylus * device's packet lengths, various maximum values, and tablet * resolution based on product ID's. * * For devices that contain 2 interfaces, wacom_features table is * inaccurate for the touch interface. Since the Interface Descriptor * for touch interfaces has pretty complete data, this function exists * to query tablet for this missing information instead of hard coding in * an additional table. * * A typical Interface Descriptor for a stylus will contain a * boot mouse application collection that is not of interest and this * function will ignore it. * * It also contains a digitizer application collection that also is not * of interest since any information it contains would be duplicate * of what is in wacom_features. Usually it defines a report of an array * of bytes that could be used as max length of the stylus packet returned. * If it happens to define a Digitizer-Stylus Physical Collection then * the X and Y logical values contain valid data but it is ignored. * * A typical Interface Descriptor for a touch interface will contain a * Digitizer-Finger Physical Collection which will define both logical * X/Y maximum as well as the physical size of tablet. Since touch * interfaces haven't supported pressure or distance, this is enough * information to override invalid values in the wacom_features table. * * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical * Collection. Instead they define a Logical Collection with a single * Logical Maximum for both X and Y. */ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, struct wacom_features *features) { struct usb_device *dev = interface_to_usbdev(intf); char limit = 0; /* result has to be defined as int for some devices */ int result = 0; int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; unsigned char *report; report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); if (!report) return -ENOMEM; /* retrive report descriptors */ do { result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, HID_DEVICET_REPORT << 8, intf->altsetting[0].desc.bInterfaceNumber, /* interface */ report, hid_desc->wDescriptorLength, 5000); /* 5 secs */ } while (result < 0 && limit++ < WAC_MSG_RETRIES); /* No need to parse the Descriptor. It isn't an error though */ if (result < 0) goto out; for (i = 0; i < hid_desc->wDescriptorLength; i++) { switch (report[i]) { case HID_USAGE_PAGE: switch (report[i + 1]) { case HID_USAGE_PAGE_DIGITIZER: usage = WCM_DIGITIZER; i++; break; case HID_USAGE_PAGE_DESKTOP: usage = WCM_DESKTOP; i++; break; } break; case HID_USAGE: switch (report[i + 1]) { case HID_USAGE_X: if (usage == WCM_DESKTOP) { if (finger) { features->device_type = BTN_TOOL_FINGER; if (features->type == TABLETPC2FG) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_TPC2FG; } if (features->type == BAMBOO_PT) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_BBTOUCH; features->x_phy = get_unaligned_le16(&report[i + 5]); features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; } else { features->x_max = get_unaligned_le16(&report[i + 3]); features->x_phy = get_unaligned_le16(&report[i + 6]); features->unit = report[i + 9]; features->unitExpo = report[i + 11]; i += 12; } } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = get_unaligned_le16(&report[i + 3]); i += 4; } } break; case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { features->device_type = BTN_TOOL_FINGER; if (features->type == TABLETPC2FG) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_TPC2FG; features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; } else if (features->type == BAMBOO_PT) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_BBTOUCH; features->y_phy = get_unaligned_le16(&report[i + 3]); features->y_max = get_unaligned_le16(&report[i + 6]); i += 12; } else { features->y_max = features->x_max; features->y_phy = get_unaligned_le16(&report[i + 3]); i += 4; } } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->y_max = get_unaligned_le16(&report[i + 3]); i += 4; } } break; case HID_USAGE_FINGER: finger = 1; i++; break; /* * Requiring Stylus Usage will ignore boot mouse * X/Y values and some cases of invalid Digitizer X/Y * values commonly reported. */ case HID_USAGE_STYLUS: pen = 1; i++; break; } break; case HID_COLLECTION_END: /* reset UsagePage and Finger */ finger = usage = 0; break; case HID_COLLECTION: i++; switch (report[i]) { case HID_COLLECTION_LOGICAL: i += wacom_parse_logical_collection(&report[i], features); break; } break; } } out: result = 0; kfree(report); return result; }
/* * URB callback routine. Called when we get IRQ reports from the * digitizer. * * This bridges the USB and input device worlds. It generates events * on the input device based on the USB reports. */ static void gtco_urb_callback(struct urb *urbinfo) { struct gtco *device = urbinfo->context; struct input_dev *inputdev; int rc; u32 val = 0; s8 valsigned = 0; char le_buffer[2]; inputdev = device->inputdevice; /* Was callback OK? */ if (urbinfo->status == -ECONNRESET || urbinfo->status == -ENOENT || urbinfo->status == -ESHUTDOWN) { /* Shutdown is occurring. Return and don't queue up any more */ return; } if (urbinfo->status != 0) { /* * Some unknown error. Hopefully temporary. Just go and * requeue an URB */ goto resubmit; } /* * Good URB, now process */ /* PID dependent when we interpret the report */ if (inputdev->id.product == PID_1000 || inputdev->id.product == PID_1001 || inputdev->id.product == PID_1002) { /* * Switch on the report ID * Conveniently, the reports have more information, the higher * the report number. We can just fall through the case * statements if we start with the highest number report */ switch (device->buffer[0]) { case 5: /* Pressure is 9 bits */ val = ((u16)(device->buffer[8]) << 1); val |= (u16)(device->buffer[7] >> 7); input_report_abs(inputdev, ABS_PRESSURE, device->buffer[8]); /* Mask out the Y tilt value used for pressure */ device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); /* Fall thru */ case 4: /* Tilt */ /* Sign extend these 7 bit numbers. */ if (device->buffer[6] & 0x40) device->buffer[6] |= 0x80; if (device->buffer[7] & 0x40) device->buffer[7] |= 0x80; valsigned = (device->buffer[6]); input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned); valsigned = (device->buffer[7]); input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned); /* Fall thru */ case 2: case 3: /* Convert buttons, only 5 bits possible */ val = (device->buffer[5]) & MASK_BUTTON; /* We don't apply any meaning to the bitmask, just report */ input_event(inputdev, EV_MSC, MSC_SERIAL, val); /* Fall thru */ case 1: /* All reports have X and Y coords in the same place */ val = get_unaligned_le16(&device->buffer[1]); input_report_abs(inputdev, ABS_X, val); val = get_unaligned_le16(&device->buffer[3]); input_report_abs(inputdev, ABS_Y, val); /* Ditto for proximity bit */ val = device->buffer[5] & MASK_INRANGE ? 1 : 0; input_report_abs(inputdev, ABS_DISTANCE, val); /* Report 1 is an exception to how we handle buttons */ /* Buttons are an index, not a bitmask */ if (device->buffer[0] == 1) { /* * Convert buttons, 5 bit index * Report value of index set as one, * the rest as 0 */ val = device->buffer[5] & MASK_BUTTON; dev_dbg(&device->intf->dev, "======>>>>>>REPORT 1: val 0x%X(%d)\n", val, val); /* * We don't apply any meaning to the button * index, just report it */ input_event(inputdev, EV_MSC, MSC_SERIAL, val); } break; case 7: /* Menu blocks */ input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); break; } } /* Other pid class */ if (inputdev->id.product == PID_400 || inputdev->id.product == PID_401) { /* Report 2 */ if (device->buffer[0] == 2) { /* Menu blocks */ input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); } /* Report 1 */ if (device->buffer[0] == 1) { char buttonbyte; /* IF X max > 64K, we still a bit from the y report */ if (device->max_X > 0x10000) { val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]); val |= (u32)(((u8)device->buffer[3] & 0x1) << 16); input_report_abs(inputdev, ABS_X, val); le_buffer[0] = (u8)((u8)(device->buffer[3]) >> 1); le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7); le_buffer[1] = (u8)(device->buffer[4] >> 1); le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7); val = get_unaligned_le16(le_buffer); input_report_abs(inputdev, ABS_Y, val); /* * Shift the button byte right by one to * make it look like the standard report */ buttonbyte = device->buffer[5] >> 1; } else {
/* control interface reports status changes with "interrupt" transfers */ static void acm_ctrl_irq(struct urb *urb) { struct acm *acm = urb->context; struct usb_cdc_notification *dr = urb->transfer_buffer; unsigned char *data; int newctrl; int retval; int status = urb->status; switch (status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, status); return; default: dbg("%s - nonzero urb status received: %d", __func__, status); goto exit; } if (!ACM_READY(acm)) goto exit; data = (unsigned char *)(dr + 1); switch (dr->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: dbg("%s network", dr->wValue ? "connected to" : "disconnected from"); break; case USB_CDC_NOTIFY_SERIAL_STATE: newctrl = get_unaligned_le16(data); if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { dbg("calling hangup"); tty_hangup(acm->tty); } acm->ctrlin = newctrl; dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c", acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-', acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); break; default: dbg("unknown notification %d received: index %d len %d data0 %d data1 %d", dr->bNotificationType, dr->wIndex, dr->wLength, data[0], data[1]); break; } exit: usb_mark_last_busy(acm->dev); retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " "result %d", __func__, retval); }
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, const unsigned char *buffer, int count, const struct h4_recv_pkt *pkts, int pkts_count) { while (count) { int i, len; if (!skb) { for (i = 0; i < pkts_count; i++) { if (buffer[0] != (&pkts[i])->type) continue; skb = bt_skb_alloc((&pkts[i])->maxlen, GFP_ATOMIC); if (!skb) return ERR_PTR(-ENOMEM); bt_cb(skb)->pkt_type = (&pkts[i])->type; bt_cb(skb)->expect = (&pkts[i])->hlen; break; } /* Check for invalid packet type */ if (!skb) return ERR_PTR(-EILSEQ); count -= 1; buffer += 1; } len = min_t(uint, bt_cb(skb)->expect - skb->len, count); memcpy(skb_put(skb, len), buffer, len); count -= len; buffer += len; /* Check for partial packet */ if (skb->len < bt_cb(skb)->expect) continue; for (i = 0; i < pkts_count; i++) { if (bt_cb(skb)->pkt_type == (&pkts[i])->type) break; } if (i >= pkts_count) { kfree_skb(skb); return ERR_PTR(-EILSEQ); } if (skb->len == (&pkts[i])->hlen) { u16 dlen; switch ((&pkts[i])->lsize) { case 0: /* No variable data length */ (&pkts[i])->recv(hdev, skb); skb = NULL; break; case 1: /* Single octet variable length */ dlen = skb->data[(&pkts[i])->loff]; bt_cb(skb)->expect += dlen; if (skb_tailroom(skb) < dlen) { kfree_skb(skb); return ERR_PTR(-EMSGSIZE); } break; case 2: /* Double octet variable length */ dlen = get_unaligned_le16(skb->data + (&pkts[i])->loff); bt_cb(skb)->expect += dlen; if (skb_tailroom(skb) < dlen) { kfree_skb(skb); return ERR_PTR(-EMSGSIZE); } break; default: /* Unsupported variable length */ kfree_skb(skb); return ERR_PTR(-EILSEQ); } } else { /* Complete frame */ (&pkts[i])->recv(hdev, skb); skb = NULL; } } return skb; }
static irqreturn_t optical_trigger_handler_debug(int irq, void *p) { #if 1 #define BAR_LEN (40) u8 buf[BAR_LEN+2]; int proxData; #ifdef REDUCED_PROX_RATE static u8 numOfData=0; static u32 heartRateSum=0; #endif gsdata->tf->read_byte(&gsdata->tb, gsdata->dev, REGS_PS1_DATA0, buf); gsdata->tf->read_byte(&gsdata->tb, gsdata->dev, REGS_PS1_DATA1, buf+1); gsdata->tf->read_byte(&gsdata->tb, gsdata->dev, REGS_IRQ_STATUS, buf+2); proxData = get_unaligned_le16(buf); if(buf[2]&BIT(2)) { proxVal = (u8)proxData; avgData = optical_HR_Average(proxData, 100); optical_HR_CalcAPW(avgData, 32 , &accData); optical_HR_DetectPeak(accData, 100, -65, &heart_rate); #ifdef REDUCED_PROX_RATE heartRateSum = heartRateSum + (u32)heart_rate; numOfData = (numOfData+1)%(100/REDUCED_PROX_RATE);//orignal prox rate is 100Hz if(numOfData==0) { heart_rate = (u16)(heartRateSum/(100/REDUCED_PROX_RATE)); heartRateSum = 0; proxValValid = true; wake_up(&proxWait); hrValValid = true; wake_up(&hrWait); printk("vung optical_trigger_handler_debug --------------"); } #else hrValValid = true; wake_up(&hrWait); proxValValid = true; wake_up(&proxWait); #endif //printk (KERN_ALERT "proxData=0x%04x,heartRate=%4d,avg=%4d,acc=%4d",proxData,heart_rate,avgData,accData); //sysfs_notify(&gsdata->dev->kobj,NULL, "prox_val"); } if(buf[2]&(BIT(5))) { gsdata->tf->read_byte(&gsdata->tb, gsdata->dev, REGS_RESPONSE, buf); printk (KERN_ALERT "CMD INT: REGS_RESPONSE=0x%x\n",buf[0]); //sysfs_notify(&gsdata->dev->kobj,NULL, "light_val"); } /* if(buf[2]&(BIT(5))) { lightVal = (u16)alsData; lightValValid = true; wake_up(&lightWait); //sysfs_notify(&gsdata->dev->kobj,NULL, "light_val"); } */ #if 0 int i; proxData = BAR_LEN*proxData/2000; for(i=0;((i<proxData)&&(i<BAR_LEN));i++) { buf[i]='='; } for(;i<BAR_LEN;i++) { buf[i]=' '; } buf[i] = '\0'; printk (KERN_ALERT "PROX: %s\n",buf); #endif #else u8 i = 16; u8 regs[16] = {0}; printk (KERN_ALERT "[%s %d]\n", __FUNCTION__,irq); for(i=0;i<16;i++) { gsdata->tf->read_byte(&gsdata->tb, gsdata->dev, i, regs+i); } for(i=0;i<16;i++) printk (KERN_ALERT "optical regs[%d]=%02x\n",i,regs[i]); #endif gsdata->tf->write_byte(&gsdata->tb, gsdata->dev, REGS_IRQ_STATUS, 0x27);//clear all return IRQ_HANDLED; }
static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw) { u16 value, index, size; u8 *read, *buff; int i, pass, ret = 0; buff = kmalloc(65536, GFP_KERNEL); if (buff == NULL) return -ENOMEM; read = kmalloc(4, GFP_KERNEL); if (!read) { kfree(buff); return -ENOMEM; } if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) goto done; deb("%*ph\n", 4, read); if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) goto done; deb("%x\n", read[0]); for (pass = 0; pass < 2; pass++) { for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { value = get_unaligned_le16(fw->data + i); i += sizeof(u16); index = get_unaligned_le16(fw->data + i); i += sizeof(u16); size = get_unaligned_le16(fw->data + i); i += sizeof(u16); if (pass == 1) { /* Will stall if using fw->data ... */ memcpy(buff, fw->data + i, size); ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), M9206_FW, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, buff, size, 20); if (ret != size) { deb("error while uploading fw!\n"); ret = -EIO; goto done; } msleep(3); } i += size; } if (i != fw->size) { deb("bad firmware file!\n"); ret = -EINVAL; goto done; } } msleep(36); /* m920x will disconnect itself from the bus after this. */ (void) m920x_write(udev, M9206_CORE, 0x01, M9206_FW_GO); deb("firmware uploaded!\n"); done: kfree(read); kfree(buff); return ret; }
static void mt76x2_apply_cal_free_data(struct mt76x2_dev *dev, u8 *efuse) { #define GROUP_5G(_id) \ MT_EE_TX_POWER_0_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id), \ MT_EE_TX_POWER_0_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id) + 1, \ MT_EE_TX_POWER_1_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id), \ MT_EE_TX_POWER_1_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id) + 1 static const u8 cal_free_bytes[] = { MT_EE_XTAL_TRIM_1, MT_EE_TX_POWER_EXT_PA_5G + 1, MT_EE_TX_POWER_0_START_2G, MT_EE_TX_POWER_0_START_2G + 1, MT_EE_TX_POWER_1_START_2G, MT_EE_TX_POWER_1_START_2G + 1, GROUP_5G(0), GROUP_5G(1), GROUP_5G(2), GROUP_5G(3), GROUP_5G(4), GROUP_5G(5), MT_EE_RF_2G_TSSI_OFF_TXPOWER, MT_EE_RF_2G_RX_HIGH_GAIN + 1, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN + 1, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN + 1, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN + 1, }; u8 *eeprom = dev->mt76.eeprom.data; u8 prev_grp0[4] = { eeprom[MT_EE_TX_POWER_0_START_5G], eeprom[MT_EE_TX_POWER_0_START_5G + 1], eeprom[MT_EE_TX_POWER_1_START_5G], eeprom[MT_EE_TX_POWER_1_START_5G + 1] }; u16 val; int i; if (!mt76x2_has_cal_free_data(dev, efuse)) return; for (i = 0; i < ARRAY_SIZE(cal_free_bytes); i++) { int offset = cal_free_bytes[i]; eeprom[offset] = efuse[offset]; } if (!(efuse[MT_EE_TX_POWER_0_START_5G] | efuse[MT_EE_TX_POWER_0_START_5G + 1])) memcpy(eeprom + MT_EE_TX_POWER_0_START_5G, prev_grp0, 2); if (!(efuse[MT_EE_TX_POWER_1_START_5G] | efuse[MT_EE_TX_POWER_1_START_5G + 1])) memcpy(eeprom + MT_EE_TX_POWER_1_START_5G, prev_grp0 + 2, 2); val = get_unaligned_le16(efuse + MT_EE_BT_RCAL_RESULT); if (val != 0xffff) eeprom[MT_EE_BT_RCAL_RESULT] = val & 0xff; val = get_unaligned_le16(efuse + MT_EE_BT_VCDL_CALIBRATION); if (val != 0xffff) eeprom[MT_EE_BT_VCDL_CALIBRATION + 1] = val >> 8; val = get_unaligned_le16(efuse + MT_EE_BT_PMUCFG); if (val != 0xffff) eeprom[MT_EE_BT_PMUCFG] = val & 0xff; }
le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7); le_buffer[1] = (u8)(device->buffer[4] >> 1); le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7); val = get_unaligned_le16(le_buffer); input_report_abs(inputdev, ABS_Y, val); /* * Shift the button byte right by one to * make it look like the standard report */ buttonbyte = device->buffer[5] >> 1; } else { val = get_unaligned_le16(&device->buffer[1]); input_report_abs(inputdev, ABS_X, val); val = get_unaligned_le16(&device->buffer[3]); input_report_abs(inputdev, ABS_Y, val); buttonbyte = device->buffer[5]; } /* BUTTONS and PROXIMITY */ val = buttonbyte & MASK_INRANGE ? 1 : 0; input_report_abs(inputdev, ABS_DISTANCE, val); /* Convert buttons, only 4 bits possible */ val = buttonbyte & 0x0F; #ifdef USE_BUTTONS
/* * Return the battery Relative State-of-Charge * Or < 0 if something fails. */ static int bq27541_battery_rsoc(struct bq27541_device_info *di) { int ret; int rsoc = 0; #if 0 int nvcap = 0,facap = 0,remcap=0,fccap=0,full=0,cnt=0; int art = 0, artte = 0, ai = 0, tte = 0, ttf = 0, si = 0; int stte = 0, mli = 0, mltte = 0, ae = 0, ap = 0, ttecp = 0, cc = 0; #endif u8 buf[2]; #if defined (CONFIG_NO_BATTERY_IC) return 100; #endif if(virtual_battery_enable == 1) return 50/*100*/; ret = bq27541_read(di->client,BQ27500_REG_SOC,buf,2); if (ret<0) { dev_err(di->dev, "error reading relative State-of-Charge\n"); return ret; } rsoc = get_unaligned_le16(buf); DBG("Enter:%s %d--rsoc = %d\n",__FUNCTION__,__LINE__,rsoc); #if defined (CONFIG_NO_BATTERY_IC) rsoc = 100; #endif #if 0 //other register information, for debug use ret = bq27541_read(di->client,0x0c,buf,2); //NominalAvailableCapacity nvcap = get_unaligned_le16(buf); DBG("\nEnter:%s %d--nvcap = %d\n",__FUNCTION__,__LINE__,nvcap); ret = bq27541_read(di->client,0x0e,buf,2); //FullAvailableCapacity facap = get_unaligned_le16(buf); DBG("Enter:%s %d--facap = %d\n",__FUNCTION__,__LINE__,facap); ret = bq27541_read(di->client,0x10,buf,2); //RemainingCapacity remcap = get_unaligned_le16(buf); DBG("Enter:%s %d--remcap = %d\n",__FUNCTION__,__LINE__,remcap); ret = bq27541_read(di->client,0x12,buf,2); //FullChargeCapacity fccap = get_unaligned_le16(buf); DBG("Enter:%s %d--fccap = %d\n",__FUNCTION__,__LINE__,fccap); ret = bq27541_read(di->client,0x3c,buf,2); //DesignCapacity full = get_unaligned_le16(buf); DBG("Enter:%s %d--DesignCapacity = %d\n",__FUNCTION__,__LINE__,full); buf[0] = 0x00; //CONTROL_STATUS buf[1] = 0x00; bq27541_write(di->client,0x00,buf,2); ret = bq27541_read(di->client,0x00,buf,2); cnt = get_unaligned_le16(buf); DBG("Enter:%s %d--Control status = %x\n",__FUNCTION__,__LINE__,cnt); ret = bq27541_read(di->client,0x02,buf,2); //AtRate art = get_unaligned_le16(buf); DBG("Enter:%s %d--AtRate = %d\n",__FUNCTION__,__LINE__,art); ret = bq27541_read(di->client,0x04,buf,2); //AtRateTimeToEmpty artte = get_unaligned_le16(buf); DBG("Enter:%s %d--AtRateTimeToEmpty = %d\n",__FUNCTION__,__LINE__,artte); ret = bq27541_read(di->client,0x14,buf,2); //AverageCurrent ai = get_unaligned_le16(buf); DBG("Enter:%s %d--AverageCurrent = %d\n",__FUNCTION__,__LINE__,ai); ret = bq27541_read(di->client,0x16,buf,2); //TimeToEmpty tte = get_unaligned_le16(buf); DBG("Enter:%s %d--TimeToEmpty = %d\n",__FUNCTION__,__LINE__,tte); ret = bq27541_read(di->client,0x18,buf,2); //TimeToFull ttf = get_unaligned_le16(buf); DBG("Enter:%s %d--TimeToFull = %d\n",__FUNCTION__,__LINE__,ttf); ret = bq27541_read(di->client,0x1a,buf,2); //StandbyCurrent si = get_unaligned_le16(buf); DBG("Enter:%s %d--StandbyCurrent = %d\n",__FUNCTION__,__LINE__,si); ret = bq27541_read(di->client,0x1c,buf,2); //StandbyTimeToEmpty stte = get_unaligned_le16(buf); DBG("Enter:%s %d--StandbyTimeToEmpty = %d\n",__FUNCTION__,__LINE__,stte); ret = bq27541_read(di->client,0x1e,buf,2); //MaxLoadCurrent mli = get_unaligned_le16(buf); DBG("Enter:%s %d--MaxLoadCurrent = %d\n",__FUNCTION__,__LINE__,mli); ret = bq27541_read(di->client,0x20,buf,2); //MaxLoadTimeToEmpty mltte = get_unaligned_le16(buf); DBG("Enter:%s %d--MaxLoadTimeToEmpty = %d\n",__FUNCTION__,__LINE__,mltte); ret = bq27541_read(di->client,0x22,buf,2); //AvailableEnergy ae = get_unaligned_le16(buf); DBG("Enter:%s %d--AvailableEnergy = %d\n",__FUNCTION__,__LINE__,ae); ret = bq27541_read(di->client,0x24,buf,2); //AveragePower ap = get_unaligned_le16(buf); DBG("Enter:%s %d--AveragePower = %d\n",__FUNCTION__,__LINE__,ap); ret = bq27541_read(di->client,0x26,buf,2); //TTEatConstantPower ttecp = get_unaligned_le16(buf); DBG("Enter:%s %d--TTEatConstantPower = %d\n",__FUNCTION__,__LINE__,ttecp); ret = bq27541_read(di->client,0x2a,buf,2); //CycleCount cc = get_unaligned_le16(buf); DBG("Enter:%s %d--CycleCount = %d\n",__FUNCTION__,__LINE__,cc); #endif return rsoc; }
/* * This is an abbreviated parser for the HID Report Descriptor. We * know what devices we are talking to, so this is by no means meant * to be generic. We can make some safe assumptions: * * - We know there are no LONG tags, all short * - We know that we have no MAIN Feature and MAIN Output items * - We know what the IRQ reports are supposed to look like. * * The main purpose of this is to use the HID report desc to figure * out the mins and maxs of the fields in the IRQ reports. The IRQ * reports for 400/401 change slightly if the max X is bigger than 64K. * */ static void parse_hid_report_descriptor(struct gtco *device, char * report, int length) { struct device *ddev = &device->intf->dev; int x, i = 0; /* Tag primitive vars */ __u8 prefix; __u8 size; __u8 tag; __u8 type; __u8 data = 0; __u16 data16 = 0; __u32 data32 = 0; /* For parsing logic */ int inputnum = 0; __u32 usage = 0; /* Global Values, indexed by TAG */ __u32 globalval[TAG_GLOB_MAX]; __u32 oldval[TAG_GLOB_MAX]; /* Debug stuff */ char maintype = 'x'; char globtype[12]; int indent = 0; char indentstr[10] = ""; dev_dbg(ddev, "======>>>>>>PARSE<<<<<<======\n"); /* Walk this report and pull out the info we need */ while (i < length) { prefix = report[i]; /* Skip over prefix */ i++; /* Determine data size and save the data in the proper variable */ size = PREF_SIZE(prefix); switch (size) { case 1: data = report[i]; break; case 2: data16 = get_unaligned_le16(&report[i]); break; case 3: size = 4; data32 = get_unaligned_le32(&report[i]); break; } /* Skip size of data */ i += size; /* What we do depends on the tag type */ tag = PREF_TAG(prefix); type = PREF_TYPE(prefix); switch (type) { case TYPE_MAIN: strcpy(globtype, ""); switch (tag) { case TAG_MAIN_INPUT: /* * The INPUT MAIN tag signifies this is * information from a report. We need to * figure out what it is and store the * min/max values */ maintype = 'I'; if (data == 2) strcpy(globtype, "Variable"); else if (data == 3) strcpy(globtype, "Var|Const"); dev_dbg(ddev, "::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits\n", globalval[TAG_GLOB_REPORT_ID], inputnum, globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]); /* We can assume that the first two input items are always the X and Y coordinates. After that, we look for everything else by local usage value */ switch (inputnum) { case 0: /* X coord */ dev_dbg(ddev, "GER: X Usage: 0x%x\n", usage); if (device->max_X == 0) { device->max_X = globalval[TAG_GLOB_LOG_MAX]; device->min_X = globalval[TAG_GLOB_LOG_MIN]; } break; case 1: /* Y coord */ dev_dbg(ddev, "GER: Y Usage: 0x%x\n", usage); if (device->max_Y == 0) { device->max_Y = globalval[TAG_GLOB_LOG_MAX]; device->min_Y = globalval[TAG_GLOB_LOG_MIN]; } break; default: /* Tilt X */ if (usage == DIGITIZER_USAGE_TILT_X) { if (device->maxtilt_X == 0) { device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; } } /* Tilt Y */ if (usage == DIGITIZER_USAGE_TILT_Y) { if (device->maxtilt_Y == 0) { device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; } } /* Pressure */ if (usage == DIGITIZER_USAGE_TIP_PRESSURE) { if (device->maxpressure == 0) { device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; device->minpressure = globalval[TAG_GLOB_LOG_MIN]; } } break; } inputnum++; break; case TAG_MAIN_OUTPUT: maintype = 'O'; break; case TAG_MAIN_FEATURE: maintype = 'F'; break; case TAG_MAIN_COL_START: maintype = 'S'; if (data == 0) { dev_dbg(ddev, "======>>>>>> Physical\n"); strcpy(globtype, "Physical"); } else dev_dbg(ddev, "======>>>>>>\n"); /* Indent the debug output */ indent++; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; /* Save global tags */ for (x = 0; x < TAG_GLOB_MAX; x++) oldval[x] = globalval[x]; break; case TAG_MAIN_COL_END: dev_dbg(ddev, "<<<<<<======\n"); maintype = 'E'; indent--; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; /* Copy global tags back */ for (x = 0; x < TAG_GLOB_MAX; x++) globalval[x] = oldval[x]; break; } switch (size) { case 1: dev_dbg(ddev, "%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x\n", indentstr, tag, maintype, size, globtype, data); break; case 2: dev_dbg(ddev, "%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x\n", indentstr, tag, maintype, size, globtype, data16); break; case 4: dev_dbg(ddev, "%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x\n", indentstr, tag, maintype, size, globtype, data32); break; } break; case TYPE_GLOBAL: switch (tag) { case TAG_GLOB_USAGE: /* * First time we hit the global usage tag, * it should tell us the type of device */ if (device->usage == 0) device->usage = data; strcpy(globtype, "USAGE"); break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "LOG_MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "LOG_MAX"); break; case TAG_GLOB_PHYS_MIN: strcpy(globtype, "PHYS_MIN"); break; case TAG_GLOB_PHYS_MAX: strcpy(globtype, "PHYS_MAX"); break; case TAG_GLOB_UNIT_EXP: strcpy(globtype, "EXP"); break; case TAG_GLOB_UNIT: strcpy(globtype, "UNIT"); break; case TAG_GLOB_REPORT_SZ: strcpy(globtype, "REPORT_SZ"); break; case TAG_GLOB_REPORT_ID: strcpy(globtype, "REPORT_ID"); /* New report, restart numbering */ inputnum = 0; break; case TAG_GLOB_REPORT_CNT: strcpy(globtype, "REPORT_CNT"); break; case TAG_GLOB_PUSH: strcpy(globtype, "PUSH"); break; case TAG_GLOB_POP: strcpy(globtype, "POP"); break; } /* Check to make sure we have a good tag number so we don't overflow array */ if (tag < TAG_GLOB_MAX) { switch (size) { case 1: dev_dbg(ddev, "%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x\n", indentstr, globtype, tag, size, data); globalval[tag] = data; break; case 2: dev_dbg(ddev, "%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x\n", indentstr, globtype, tag, size, data16); globalval[tag] = data16; break; case 4: dev_dbg(ddev, "%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x\n", indentstr, globtype, tag, size, data32); globalval[tag] = data32; break; } } else { dev_dbg(ddev, "%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d\n", indentstr, tag, size); } break; case TYPE_LOCAL: switch (tag) { case TAG_GLOB_USAGE: strcpy(globtype, "USAGE"); /* Always 1 byte */ usage = data; break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "MAX"); break; default: strcpy(globtype, "UNKNOWN"); break; } switch (size) { case 1: dev_dbg(ddev, "%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x\n", indentstr, tag, globtype, size, data); break; case 2: dev_dbg(ddev, "%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x\n", indentstr, tag, globtype, size, data16); break; case 4: dev_dbg(ddev, "%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x\n", indentstr, tag, globtype, size, data32); break; } break; } } }
int ieee80211_radiotap_iterator_init( struct ieee80211_radiotap_iterator *iterator, struct ieee80211_radiotap_header *radiotap_header, int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) { if (max_length < (int)sizeof(struct ieee80211_radiotap_header)) return -EINVAL; /* Linux only supports version 0 radiotap format */ if (radiotap_header->it_version) return -EINVAL; /* sanity check for allowed length and radiotap length field */ if (max_length < get_unaligned_le16(&radiotap_header->it_len)) return -EINVAL; iterator->_rtheader = radiotap_header; iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len); iterator->_arg_index = 0; iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present); iterator->_arg = (guint8 *)radiotap_header + sizeof(*radiotap_header); iterator->_reset_on_ext = 0; iterator->_next_bitmap = &radiotap_header->it_present; iterator->_next_bitmap++; iterator->_vns = vns; iterator->current_namespace = &radiotap_ns; iterator->is_radiotap_ns = 1; #ifdef RADIOTAP_SUPPORT_OVERRIDES iterator->n_overrides = 0; iterator->overrides = NULL; #endif /* find payload start allowing for extended bitmap(s) */ if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) { if (!ITERATOR_VALID(iterator, sizeof(guint32))) return -EINVAL; while (get_unaligned_le32(iterator->_arg) & (1 << IEEE80211_RADIOTAP_EXT)) { iterator->_arg += sizeof(guint32); /* * check for insanity where the present bitmaps * keep claiming to extend up to or even beyond the * stated radiotap header length */ if (!ITERATOR_VALID(iterator, sizeof(guint32))) return -EINVAL; } iterator->_arg += sizeof(guint32); /* * no need to check again for blowing past stated radiotap * header length, because ieee80211_radiotap_iterator_next * checks it before it is dereferenced */ } iterator->this_arg = iterator->_arg; /* we are all initialized happily */ return 0; }
static void notification_available_cb(struct urb *urb) { int status; struct usb_cdc_notification *ctrl; struct ctrl_bridge *dev = urb->context; struct bridge *brdg = dev->brdg; unsigned int ctrl_bits; unsigned char *data; unsigned long flags; /*usb device disconnect*/ if (urb->dev->state == USB_STATE_NOTATTACHED) return; spin_lock_irqsave(&dev->lock, flags); dev->rx_state = RX_IDLE; spin_unlock_irqrestore(&dev->lock, flags); switch (urb->status) { case 0: /*success*/ break; case -ESHUTDOWN: case -ENOENT: case -ECONNRESET: case -EPROTO: /* unplug */ return; case -EPIPE: dev_err(&dev->intf->dev, "%s: stall on int endpoint\n", __func__); /* TBD : halt to be cleared in work */ case -EOVERFLOW: default: pr_debug_ratelimited("%s: non zero urb status = %d\n", __func__, urb->status); goto resubmit_int_urb; } ctrl = (struct usb_cdc_notification *)urb->transfer_buffer; data = (unsigned char *)(ctrl + 1); switch (ctrl->bNotificationType) { case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: spin_lock_irqsave(&dev->lock, flags); dev->rx_state = RX_BUSY; spin_unlock_irqrestore(&dev->lock, flags); dev->resp_avail++; usb_autopm_get_interface_no_resume(dev->intf); usb_fill_control_urb(dev->readurb, dev->udev, usb_rcvctrlpipe(dev->udev, 0), (unsigned char *)dev->in_ctlreq, dev->readbuf, DEFAULT_READ_URB_LENGTH, resp_avail_cb, dev); status = usb_submit_urb(dev->readurb, GFP_ATOMIC); if (status) { dev_err(&dev->intf->dev, "%s: Error submitting Read URB %d\n", __func__, status); usb_autopm_put_interface_async(dev->intf); goto resubmit_int_urb; } return; case USB_CDC_NOTIFY_NETWORK_CONNECTION: dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ? "connected to" : "disconnected from"); break; case USB_CDC_NOTIFY_SERIAL_STATE: dev->notify_ser_state++; ctrl_bits = get_unaligned_le16(data); dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits); dev->cbits_tohost = ctrl_bits; if (brdg && brdg->ops.send_cbits) brdg->ops.send_cbits(brdg->ctx, ctrl_bits); break; default: dev_err(&dev->intf->dev, "%s: unknown notification %d received:" "index %d len %d data0 %d data1 %d", __func__, ctrl->bNotificationType, ctrl->wIndex, ctrl->wLength, data[0], data[1]); } resubmit_int_urb: ctrl_bridge_start_read(dev, GFP_ATOMIC); }
static void notification_available_cb(struct urb *urb) { int status; struct usb_cdc_notification *ctrl; struct usb_device *udev; struct ctrl_bridge *dev = urb->context; struct bridge *brdg = dev->brdg; unsigned int ctrl_bits; unsigned char *data; unsigned int iface_num; /* if this intf is already disconnected, this urb free-ed before * calling from qh_completions. just return and do nothing */ if (!dev->intf) return; udev = interface_to_usbdev(dev->intf); iface_num = dev->intf->cur_altsetting->desc.bInterfaceNumber; switch (urb->status) { case 0: pr_info("[NACB:%d]<\n", iface_num); /*success*/ break; case -ESHUTDOWN: case -ENOENT: case -ECONNRESET: case -EPROTO: /* unplug */ return; case -EPIPE: dev_err(&udev->dev, "%s: stall on int endpoint\n", __func__); /* TBD : halt to be cleared in work */ case -EOVERFLOW: default: pr_debug_ratelimited("%s: non zero urb status = %d\n", __func__, urb->status); goto resubmit_int_urb; } ctrl = (struct usb_cdc_notification *)urb->transfer_buffer; data = (unsigned char *)(ctrl + 1); switch (ctrl->bNotificationType) { case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: dev->resp_avail++; usb_fill_control_urb(dev->readurb, udev, usb_rcvctrlpipe(udev, 0), (unsigned char *)dev->in_ctlreq, dev->readbuf, DEFAULT_READ_URB_LENGTH, resp_avail_cb, dev); status = usb_submit_urb(dev->readurb, GFP_ATOMIC); if (status) { dev_err(&udev->dev, "%s: Error submitting Read URB %d\n", __func__, status); goto resubmit_int_urb; } else pr_info("[NRA:%d]>\n", iface_num); return; case USB_CDC_NOTIFY_NETWORK_CONNECTION: dev_dbg(&udev->dev, "%s network\n", ctrl->wValue ? "connected to" : "disconnected from"); break; case USB_CDC_NOTIFY_SERIAL_STATE: dev->notify_ser_state++; ctrl_bits = get_unaligned_le16(data); dev_dbg(&udev->dev, "serial state: %d\n", ctrl_bits); dev->cbits_tohost = ctrl_bits; if (brdg && brdg->ops.send_cbits) brdg->ops.send_cbits(brdg->ctx, ctrl_bits); #ifdef CONFIG_MDM_HSIC_PM pr_info("%s: set lpa handling to false\n", __func__); lpa_handling = false; #endif break; default: dev_err(&udev->dev, "%s: unknown notification %d received:" "index %d len %d data0 %d data1 %d", __func__, ctrl->bNotificationType, ctrl->wIndex, ctrl->wLength, data[0], data[1]); } resubmit_int_urb: status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n", __func__, status); } else pr_info("[CHKRA:%d]>\n", iface_num); }